init 2
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
package com.sisvietnamvn.web;
|
||||
|
||||
import com.sisvietnamvn.web.config.AsyncSyncConfiguration;
|
||||
import com.sisvietnamvn.web.config.EmbeddedSQL;
|
||||
import com.sisvietnamvn.web.config.JacksonConfiguration;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
/**
|
||||
* Base composite annotation for integration tests.
|
||||
*/
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@SpringBootTest(
|
||||
classes = {
|
||||
SisvietnamvnApp.class,
|
||||
JacksonConfiguration.class,
|
||||
AsyncSyncConfiguration.class,
|
||||
com.sisvietnamvn.web.config.JacksonHibernateConfiguration.class,
|
||||
}
|
||||
)
|
||||
@EmbeddedSQL
|
||||
public @interface IntegrationTest {}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.sisvietnamvn.web;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class SisvietnamvnApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.sisvietnamvn.web;
|
||||
|
||||
import static com.tngtech.archunit.base.DescribedPredicate.alwaysTrue;
|
||||
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.belongToAnyOf;
|
||||
import static com.tngtech.archunit.library.Architectures.layeredArchitecture;
|
||||
|
||||
import com.tngtech.archunit.core.importer.ImportOption.DoNotIncludeTests;
|
||||
import com.tngtech.archunit.junit.AnalyzeClasses;
|
||||
import com.tngtech.archunit.junit.ArchTest;
|
||||
import com.tngtech.archunit.lang.ArchRule;
|
||||
|
||||
@AnalyzeClasses(packagesOf = SisvietnamvnApp.class, importOptions = DoNotIncludeTests.class)
|
||||
class TechnicalStructureTest {
|
||||
|
||||
// prettier-ignore
|
||||
@ArchTest
|
||||
static final ArchRule respectsTechnicalArchitectureLayers = layeredArchitecture()
|
||||
.consideringAllDependencies()
|
||||
.layer("Config").definedBy("..config..")
|
||||
.layer("Web").definedBy("..web..")
|
||||
.optionalLayer("Service").definedBy("..service..")
|
||||
.layer("Security").definedBy("..security..")
|
||||
.optionalLayer("Persistence").definedBy("..repository..")
|
||||
.layer("Domain").definedBy("..domain..")
|
||||
|
||||
.whereLayer("Config").mayNotBeAccessedByAnyLayer()
|
||||
.whereLayer("Web").mayOnlyBeAccessedByLayers("Config")
|
||||
.whereLayer("Service").mayOnlyBeAccessedByLayers("Web", "Config")
|
||||
.whereLayer("Security").mayOnlyBeAccessedByLayers("Config", "Service", "Web")
|
||||
.whereLayer("Persistence").mayOnlyBeAccessedByLayers("Service", "Security", "Web", "Config")
|
||||
.whereLayer("Domain").mayOnlyBeAccessedByLayers("Persistence", "Service", "Security", "Web", "Config")
|
||||
|
||||
.ignoreDependency(belongToAnyOf(SisvietnamvnApp.class), alwaysTrue())
|
||||
.ignoreDependency(alwaysTrue(), belongToAnyOf(
|
||||
com.sisvietnamvn.web.config.Constants.class,
|
||||
com.sisvietnamvn.web.config.ApplicationProperties.class
|
||||
));
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
package com.sisvietnamvn.web.config;
|
||||
|
||||
import java.util.concurrent.Executor;
|
||||
import org.springframework.boot.test.context.TestConfiguration;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.core.task.SyncTaskExecutor;
|
||||
|
||||
@TestConfiguration(proxyBeanMethods = false)
|
||||
public class AsyncSyncConfiguration {
|
||||
|
||||
@Bean(name = "taskExecutor")
|
||||
public Executor taskExecutor() {
|
||||
return new SyncTaskExecutor();
|
||||
}
|
||||
}
|
||||
+132
@@ -0,0 +1,132 @@
|
||||
package com.sisvietnamvn.web.config;
|
||||
|
||||
import static org.assertj.core.api.AssertionsForClassTypes.assertThat;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import ch.qos.logback.classic.spi.ILoggingEvent;
|
||||
import java.util.List;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.slf4j.Marker;
|
||||
import org.slf4j.MarkerFactory;
|
||||
import org.springframework.boot.ansi.AnsiColor;
|
||||
import org.springframework.boot.ansi.AnsiElement;
|
||||
|
||||
class CRLFLogConverterTest {
|
||||
|
||||
@Test
|
||||
void transformShouldReturnInputStringWhenMarkerListIsEmpty() {
|
||||
ILoggingEvent event = mock(ILoggingEvent.class);
|
||||
when(event.getMarkerList()).thenReturn(null);
|
||||
when(event.getLoggerName()).thenReturn("org.hibernate.example.Logger");
|
||||
String input = "Test input string";
|
||||
CRLFLogConverter converter = new CRLFLogConverter();
|
||||
|
||||
String result = converter.transform(event, input);
|
||||
|
||||
assertEquals(input, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void transformShouldReturnInputStringWhenMarkersContainCRLFSafeMarker() {
|
||||
ILoggingEvent event = mock(ILoggingEvent.class);
|
||||
Marker marker = MarkerFactory.getMarker("CRLF_SAFE");
|
||||
List<Marker> markers = List.of(marker);
|
||||
when(event.getMarkerList()).thenReturn(markers);
|
||||
String input = "Test input string";
|
||||
CRLFLogConverter converter = new CRLFLogConverter();
|
||||
|
||||
String result = converter.transform(event, input);
|
||||
|
||||
assertEquals(input, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void transformShouldReturnInputStringWhenMarkersNotContainCRLFSafeMarker() {
|
||||
ILoggingEvent event = mock(ILoggingEvent.class);
|
||||
Marker marker = MarkerFactory.getMarker("CRLF_NOT_SAFE");
|
||||
List<Marker> markers = List.of(marker);
|
||||
when(event.getMarkerList()).thenReturn(markers);
|
||||
when(event.getLoggerName()).thenReturn("org.hibernate.example.Logger");
|
||||
String input = "Test input string";
|
||||
CRLFLogConverter converter = new CRLFLogConverter();
|
||||
|
||||
String result = converter.transform(event, input);
|
||||
|
||||
assertEquals(input, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void transformShouldReturnInputStringWhenLoggerIsSafe() {
|
||||
ILoggingEvent event = mock(ILoggingEvent.class);
|
||||
when(event.getLoggerName()).thenReturn("org.hibernate.example.Logger");
|
||||
String input = "Test input string";
|
||||
CRLFLogConverter converter = new CRLFLogConverter();
|
||||
|
||||
String result = converter.transform(event, input);
|
||||
|
||||
assertEquals(input, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void transformShouldReplaceNewlinesAndCarriageReturnsWithUnderscoreWhenMarkersDoNotContainCRLFSafeMarkerAndLoggerIsNotSafe() {
|
||||
ILoggingEvent event = mock(ILoggingEvent.class);
|
||||
List<Marker> markers = List.of();
|
||||
when(event.getMarkerList()).thenReturn(markers);
|
||||
when(event.getLoggerName()).thenReturn("com.mycompany.myapp.example.Logger");
|
||||
String input = "Test\ninput\rstring";
|
||||
CRLFLogConverter converter = new CRLFLogConverter();
|
||||
|
||||
String result = converter.transform(event, input);
|
||||
|
||||
assertEquals("Test_input_string", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void transformShouldReplaceNewlinesAndCarriageReturnsWithAnsiStringWhenMarkersDoNotContainCRLFSafeMarkerAndLoggerIsNotSafeAndAnsiElementIsNotNull() {
|
||||
ILoggingEvent event = mock(ILoggingEvent.class);
|
||||
List<Marker> markers = List.of();
|
||||
when(event.getMarkerList()).thenReturn(markers);
|
||||
when(event.getLoggerName()).thenReturn("com.mycompany.myapp.example.Logger");
|
||||
String input = "Test\ninput\rstring";
|
||||
CRLFLogConverter converter = new CRLFLogConverter();
|
||||
converter.setOptionList(List.of("red"));
|
||||
|
||||
String result = converter.transform(event, input);
|
||||
|
||||
assertEquals("Test_input_string", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLoggerSafeShouldReturnTrueWhenLoggerNameStartsWithSafeLogger() {
|
||||
ILoggingEvent event = mock(ILoggingEvent.class);
|
||||
when(event.getLoggerName()).thenReturn("org.springframework.boot.autoconfigure.example.Logger");
|
||||
CRLFLogConverter converter = new CRLFLogConverter();
|
||||
|
||||
boolean result = converter.isLoggerSafe(event);
|
||||
|
||||
assertTrue(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void isLoggerSafeShouldReturnFalseWhenLoggerNameDoesNotStartWithSafeLogger() {
|
||||
ILoggingEvent event = mock(ILoggingEvent.class);
|
||||
when(event.getLoggerName()).thenReturn("com.mycompany.myapp.example.Logger");
|
||||
CRLFLogConverter converter = new CRLFLogConverter();
|
||||
|
||||
boolean result = converter.isLoggerSafe(event);
|
||||
|
||||
assertFalse(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testToAnsiString() {
|
||||
CRLFLogConverter cut = new CRLFLogConverter();
|
||||
AnsiElement ansiElement = AnsiColor.RED;
|
||||
|
||||
String result = cut.toAnsiString("input", ansiElement);
|
||||
|
||||
assertThat(result).isEqualTo("input");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package com.sisvietnamvn.web.config;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface EmbeddedSQL {}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
package com.sisvietnamvn.web.config;
|
||||
|
||||
import com.sisvietnamvn.web.IntegrationTest;
|
||||
import java.util.Comparator;
|
||||
import org.junit.jupiter.api.ClassDescriptor;
|
||||
import org.junit.jupiter.api.ClassOrderer;
|
||||
import org.junit.jupiter.api.ClassOrdererContext;
|
||||
|
||||
public class SpringBootTestClassOrderer implements ClassOrderer {
|
||||
|
||||
@Override
|
||||
public void orderClasses(ClassOrdererContext context) {
|
||||
context.getClassDescriptors().sort(Comparator.comparingInt(SpringBootTestClassOrderer::getOrder));
|
||||
}
|
||||
|
||||
private static int getOrder(ClassDescriptor classDescriptor) {
|
||||
if (classDescriptor.findAnnotation(IntegrationTest.class).isPresent()) {
|
||||
return 2;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.sisvietnamvn.web.config;
|
||||
|
||||
import org.testcontainers.containers.JdbcDatabaseContainer;
|
||||
|
||||
public interface SqlTestContainer {
|
||||
JdbcDatabaseContainer<?> getTestContainer();
|
||||
}
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
package com.sisvietnamvn.web.config;
|
||||
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
|
||||
import org.springframework.boot.test.util.TestPropertyValues;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.test.context.ContextConfigurationAttributes;
|
||||
import org.springframework.test.context.ContextCustomizer;
|
||||
import org.springframework.test.context.ContextCustomizerFactory;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
import tech.jhipster.config.JHipsterConstants;
|
||||
|
||||
public class SqlTestContainersSpringContextCustomizerFactory implements ContextCustomizerFactory {
|
||||
|
||||
private final Logger log = LoggerFactory.getLogger(SqlTestContainersSpringContextCustomizerFactory.class);
|
||||
|
||||
private static SqlTestContainer prodTestcontainer;
|
||||
|
||||
@Override
|
||||
public ContextCustomizer createContextCustomizer(Class<?> testClass, List<ContextConfigurationAttributes> configAttributes) {
|
||||
return new ContextCustomizer() {
|
||||
@Override
|
||||
public void customizeContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
|
||||
ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();
|
||||
TestPropertyValues testValues = TestPropertyValues.empty();
|
||||
EmbeddedSQL sqlAnnotation = AnnotatedElementUtils.findMergedAnnotation(testClass, EmbeddedSQL.class);
|
||||
boolean usingTestProdProfile = List.of(context.getEnvironment().getActiveProfiles()).contains(
|
||||
"test" + JHipsterConstants.SPRING_PROFILE_PRODUCTION
|
||||
);
|
||||
if (null != sqlAnnotation && usingTestProdProfile) {
|
||||
log.debug("detected the EmbeddedSQL annotation on class {}", testClass.getName());
|
||||
log.info("Warming up the sql database");
|
||||
if (null == prodTestcontainer) {
|
||||
try {
|
||||
Class<? extends SqlTestContainer> containerClass = Class.forName(
|
||||
this.getClass().getPackageName() + ".DatabaseTestcontainer"
|
||||
).asSubclass(SqlTestContainer.class);
|
||||
prodTestcontainer = beanFactory.createBean(containerClass);
|
||||
beanFactory.registerSingleton(containerClass.getName(), prodTestcontainer);
|
||||
/**
|
||||
* ((DefaultListableBeanFactory)beanFactory).registerDisposableBean(containerClass.getName(), prodTestcontainer);
|
||||
*/
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
testValues = testValues.and("spring.datasource.url=" + prodTestcontainer.getTestContainer().getJdbcUrl() + "");
|
||||
testValues = testValues.and("spring.datasource.username=" + prodTestcontainer.getTestContainer().getUsername());
|
||||
testValues = testValues.and("spring.datasource.password=" + prodTestcontainer.getTestContainer().getPassword());
|
||||
}
|
||||
testValues.applyTo(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return SqlTestContainer.class.getName().hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
return this.hashCode() == obj.hashCode();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package com.sisvietnamvn.web.config;
|
||||
|
||||
import static org.mockito.Mockito.*;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.options;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import jakarta.servlet.*;
|
||||
import java.util.*;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.mock.env.MockEnvironment;
|
||||
import org.springframework.mock.web.MockServletContext;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import tech.jhipster.config.JHipsterProperties;
|
||||
|
||||
/**
|
||||
* Unit tests for the {@link WebConfigurer} class.
|
||||
*/
|
||||
class WebConfigurerTest {
|
||||
|
||||
private WebConfigurer webConfigurer;
|
||||
|
||||
private MockServletContext servletContext;
|
||||
|
||||
private MockEnvironment env;
|
||||
|
||||
private JHipsterProperties props;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
servletContext = spy(new MockServletContext());
|
||||
doReturn(mock(FilterRegistration.Dynamic.class)).when(servletContext).addFilter(anyString(), any(Filter.class));
|
||||
doReturn(mock(ServletRegistration.Dynamic.class)).when(servletContext).addServlet(anyString(), any(Servlet.class));
|
||||
|
||||
env = new MockEnvironment();
|
||||
props = new JHipsterProperties();
|
||||
|
||||
webConfigurer = new WebConfigurer(env, props);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCorsFilterOnApiPath() throws Exception {
|
||||
props.getCors().setAllowedOrigins(List.of("other.domain.com"));
|
||||
props.getCors().setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
|
||||
props.getCors().setAllowedHeaders(List.of("*"));
|
||||
props.getCors().setMaxAge(1800L);
|
||||
props.getCors().setAllowCredentials(true);
|
||||
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new WebConfigurerTestController()).addFilters(webConfigurer.corsFilter()).build();
|
||||
|
||||
mockMvc
|
||||
.perform(
|
||||
options("/api/test-cors")
|
||||
.header(HttpHeaders.ORIGIN, "other.domain.com")
|
||||
.header(HttpHeaders.ACCESS_CONTROL_REQUEST_METHOD, "POST")
|
||||
)
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "other.domain.com"))
|
||||
.andExpect(header().string(HttpHeaders.VARY, "Origin"))
|
||||
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS, "GET,POST,PUT,DELETE"))
|
||||
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS, "true"))
|
||||
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_MAX_AGE, "1800"));
|
||||
|
||||
mockMvc
|
||||
.perform(get("/api/test-cors").header(HttpHeaders.ORIGIN, "other.domain.com"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().string(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN, "other.domain.com"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCorsFilterOnOtherPath() throws Exception {
|
||||
props.getCors().setAllowedOrigins(List.of("*"));
|
||||
props.getCors().setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE"));
|
||||
props.getCors().setAllowedHeaders(List.of("*"));
|
||||
props.getCors().setMaxAge(1800L);
|
||||
props.getCors().setAllowCredentials(true);
|
||||
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new WebConfigurerTestController()).addFilters(webConfigurer.corsFilter()).build();
|
||||
|
||||
mockMvc
|
||||
.perform(get("/test/test-cors").header(HttpHeaders.ORIGIN, "other.domain.com"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCorsFilterDeactivatedForNullAllowedOrigins() throws Exception {
|
||||
props.getCors().setAllowedOrigins(null);
|
||||
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new WebConfigurerTestController()).addFilters(webConfigurer.corsFilter()).build();
|
||||
|
||||
mockMvc
|
||||
.perform(get("/api/test-cors").header(HttpHeaders.ORIGIN, "other.domain.com"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldCorsFilterDeactivatedForEmptyAllowedOrigins() throws Exception {
|
||||
props.getCors().setAllowedOrigins(new ArrayList<>());
|
||||
|
||||
MockMvc mockMvc = MockMvcBuilders.standaloneSetup(new WebConfigurerTestController()).addFilters(webConfigurer.corsFilter()).build();
|
||||
|
||||
mockMvc
|
||||
.perform(get("/api/test-cors").header(HttpHeaders.ORIGIN, "other.domain.com"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(header().doesNotExist(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN));
|
||||
}
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
package com.sisvietnamvn.web.config;
|
||||
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
@RestController
|
||||
public class WebConfigurerTestController {
|
||||
|
||||
@GetMapping("/api/test-cors")
|
||||
public void testCorsOnApiPath() {
|
||||
// empty method
|
||||
}
|
||||
|
||||
@GetMapping("/test/test-cors")
|
||||
public void testCorsOnOtherPath() {
|
||||
// empty method
|
||||
}
|
||||
}
|
||||
+171
@@ -0,0 +1,171 @@
|
||||
package com.sisvietnamvn.web.config.timezone;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.sisvietnamvn.web.IntegrationTest;
|
||||
import com.sisvietnamvn.web.repository.timezone.DateTimeWrapper;
|
||||
import com.sisvietnamvn.web.repository.timezone.DateTimeWrapperRepository;
|
||||
import java.time.*;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.jdbc.core.JdbcTemplate;
|
||||
import org.springframework.jdbc.support.rowset.SqlRowSet;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests for verifying the behavior of Hibernate in the context of storing various date and time types across different databases.
|
||||
* The tests focus on ensuring that the stored values are correctly transformed and stored according to the configured timezone.
|
||||
* Timezone is environment specific, and can be adjusted according to your needs.
|
||||
*
|
||||
* For more context, refer to:
|
||||
* - GitHub Issue: https://github.com/jhipster/generator-jhipster/issues/22579
|
||||
* - Pull Request: https://github.com/jhipster/generator-jhipster/pull/22946
|
||||
*/
|
||||
@IntegrationTest
|
||||
class HibernateTimeZoneIT {
|
||||
|
||||
@Autowired
|
||||
private DateTimeWrapperRepository dateTimeWrapperRepository;
|
||||
|
||||
@Autowired
|
||||
private JdbcTemplate jdbcTemplate;
|
||||
|
||||
@Value("${spring.jpa.properties.hibernate.jdbc.time_zone:UTC}")
|
||||
private String zoneId;
|
||||
|
||||
private DateTimeWrapper dateTimeWrapper;
|
||||
private DateTimeFormatter dateTimeFormatter;
|
||||
private DateTimeFormatter timeFormatter;
|
||||
private DateTimeFormatter offsetTimeFormatter;
|
||||
private DateTimeFormatter dateFormatter;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
dateTimeWrapper = new DateTimeWrapper();
|
||||
dateTimeWrapper.setInstant(Instant.parse("2014-11-12T05:10:00.0Z"));
|
||||
dateTimeWrapper.setLocalDateTime(LocalDateTime.parse("2014-11-12T07:20:00.0"));
|
||||
dateTimeWrapper.setOffsetDateTime(OffsetDateTime.parse("2011-12-14T08:30:00.0Z"));
|
||||
dateTimeWrapper.setZonedDateTime(ZonedDateTime.parse("2011-12-14T08:40:00.0Z"));
|
||||
dateTimeWrapper.setLocalTime(LocalTime.parse("14:50:00"));
|
||||
dateTimeWrapper.setOffsetTime(OffsetTime.parse("14:00:00+02:00"));
|
||||
dateTimeWrapper.setLocalDate(LocalDate.parse("2016-09-10"));
|
||||
|
||||
dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S").withZone(ZoneId.of(zoneId));
|
||||
timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss").withZone(ZoneId.of(zoneId));
|
||||
offsetTimeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
|
||||
dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void storeInstantWithZoneIdConfigShouldBeStoredOnConfiguredTimeZone() {
|
||||
dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper);
|
||||
|
||||
String request = generateSqlRequest("instant", dateTimeWrapper.getId());
|
||||
SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request);
|
||||
String expectedValue = dateTimeFormatter.format(dateTimeWrapper.getInstant());
|
||||
|
||||
assertThatValueFromSqlRowSetIsEqualToExpectedValue(resultSet, expectedValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void storeLocalDateTimeWithZoneIdConfigShouldBeStoredOnConfiguredTimeZone() {
|
||||
dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper);
|
||||
|
||||
String request = generateSqlRequest("local_date_time", dateTimeWrapper.getId());
|
||||
SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request);
|
||||
String expectedValue = dateTimeWrapper.getLocalDateTime().atZone(ZoneId.systemDefault()).format(dateTimeFormatter);
|
||||
|
||||
assertThatValueFromSqlRowSetIsEqualToExpectedValue(resultSet, expectedValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void storeOffsetDateTimeWithZoneIdConfigShouldBeStoredOnConfiguredTimeZone() {
|
||||
dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper);
|
||||
|
||||
String request = generateSqlRequest("offset_date_time", dateTimeWrapper.getId());
|
||||
SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request);
|
||||
String expectedValue = dateTimeWrapper.getOffsetDateTime().format(dateTimeFormatter);
|
||||
|
||||
assertThatValueFromSqlRowSetIsEqualToExpectedValue(resultSet, expectedValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void storeZoneDateTimeWithZoneIdConfigShouldBeStoredOnConfiguredTimeZone() {
|
||||
dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper);
|
||||
|
||||
String request = generateSqlRequest("zoned_date_time", dateTimeWrapper.getId());
|
||||
SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request);
|
||||
String expectedValue = dateTimeWrapper.getZonedDateTime().format(dateTimeFormatter);
|
||||
|
||||
assertThatValueFromSqlRowSetIsEqualToExpectedValue(resultSet, expectedValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void storeLocalTimeWithZoneIdConfigShouldBeStoredOnConfiguredTimeZoneAccordingToHis1stJan1970Value() {
|
||||
dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper);
|
||||
|
||||
String request = generateSqlRequest("local_time", dateTimeWrapper.getId());
|
||||
SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request);
|
||||
String expectedValue = dateTimeWrapper
|
||||
.getLocalTime()
|
||||
.atDate(LocalDate.of(1970, Month.JANUARY, 1))
|
||||
.atZone(ZoneId.systemDefault())
|
||||
.format(timeFormatter);
|
||||
|
||||
assertThatValueFromSqlRowSetIsEqualToExpectedValue(resultSet, expectedValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void storeOffsetTimeWithZoneIdConfigShouldBeStoredOnConfiguredTimeZoneAccordingToHis1stJan1970Value() {
|
||||
dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper);
|
||||
|
||||
String request = generateSqlRequest("offset_time", dateTimeWrapper.getId());
|
||||
SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request);
|
||||
String expectedValue = dateTimeWrapper
|
||||
.getOffsetTime()
|
||||
// Convert to configured timezone
|
||||
.withOffsetSameInstant(ZoneId.of(zoneId).getRules().getOffset(Instant.now()))
|
||||
// Normalize to System TimeZone.
|
||||
// this behavior looks a bug, refer to https://github.com/jhipster/generator-jhipster/issues/22579.
|
||||
.withOffsetSameLocal(OffsetDateTime.ofInstant(Instant.EPOCH, ZoneId.systemDefault()).getOffset())
|
||||
// Convert the normalized value to configured timezone
|
||||
.withOffsetSameInstant(ZoneId.of(zoneId).getRules().getOffset(Instant.EPOCH))
|
||||
.format(offsetTimeFormatter);
|
||||
|
||||
assertThatValueFromSqlRowSetIsEqualToExpectedValue(resultSet, expectedValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void storeLocalDateWithZoneIdConfigShouldBeStoredWithoutTransformation() {
|
||||
dateTimeWrapperRepository.saveAndFlush(dateTimeWrapper);
|
||||
|
||||
String request = generateSqlRequest("local_date", dateTimeWrapper.getId());
|
||||
SqlRowSet resultSet = jdbcTemplate.queryForRowSet(request);
|
||||
String expectedValue = dateTimeWrapper.getLocalDate().format(dateFormatter);
|
||||
|
||||
assertThatValueFromSqlRowSetIsEqualToExpectedValue(resultSet, expectedValue);
|
||||
}
|
||||
|
||||
private String generateSqlRequest(String fieldName, long id) {
|
||||
return "SELECT %s FROM jhi_date_time_wrapper where id=%d".formatted(fieldName, id);
|
||||
}
|
||||
|
||||
private void assertThatValueFromSqlRowSetIsEqualToExpectedValue(SqlRowSet sqlRowSet, String expectedValue) {
|
||||
while (sqlRowSet.next()) {
|
||||
String dbValue = sqlRowSet.getString(1);
|
||||
|
||||
assertThat(dbValue).isNotNull();
|
||||
assertThat(dbValue).isEqualTo(expectedValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package com.sisvietnamvn.web.domain;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.ZoneOffset;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.util.Comparator;
|
||||
|
||||
public class AssertUtils {
|
||||
|
||||
public static Comparator<ZonedDateTime> zonedDataTimeSameInstant = Comparator.nullsFirst((e1, a2) ->
|
||||
e1.withZoneSameInstant(ZoneOffset.UTC).compareTo(a2.withZoneSameInstant(ZoneOffset.UTC))
|
||||
);
|
||||
|
||||
public static Comparator<BigDecimal> bigDecimalCompareTo = Comparator.nullsFirst(BigDecimal::compareTo);
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
package com.sisvietnamvn.web.domain;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class AuthorityAsserts {
|
||||
|
||||
/**
|
||||
* Asserts that the entity has all properties (fields/relationships) set.
|
||||
*
|
||||
* @param expected the expected entity
|
||||
* @param actual the actual entity
|
||||
*/
|
||||
public static void assertAuthorityAllPropertiesEquals(Authority expected, Authority actual) {
|
||||
assertAuthorityAutoGeneratedPropertiesEquals(expected, actual);
|
||||
assertAuthorityAllUpdatablePropertiesEquals(expected, actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the entity has all updatable properties (fields/relationships) set.
|
||||
*
|
||||
* @param expected the expected entity
|
||||
* @param actual the actual entity
|
||||
*/
|
||||
public static void assertAuthorityAllUpdatablePropertiesEquals(Authority expected, Authority actual) {
|
||||
assertAuthorityUpdatableFieldsEquals(expected, actual);
|
||||
assertAuthorityUpdatableRelationshipsEquals(expected, actual);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the entity has all the auto generated properties (fields/relationships) set.
|
||||
*
|
||||
* @param expected the expected entity
|
||||
* @param actual the actual entity
|
||||
*/
|
||||
public static void assertAuthorityAutoGeneratedPropertiesEquals(Authority expected, Authority actual) {
|
||||
// empty method
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the entity has all the updatable fields set.
|
||||
*
|
||||
* @param expected the expected entity
|
||||
* @param actual the actual entity
|
||||
*/
|
||||
public static void assertAuthorityUpdatableFieldsEquals(Authority expected, Authority actual) {
|
||||
assertThat(actual)
|
||||
.as("Verify Authority relevant properties")
|
||||
.satisfies(a -> assertThat(a.getName()).as("check name").isEqualTo(expected.getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that the entity has all the updatable relationships set.
|
||||
*
|
||||
* @param expected the expected entity
|
||||
* @param actual the actual entity
|
||||
*/
|
||||
public static void assertAuthorityUpdatableRelationshipsEquals(Authority expected, Authority actual) {
|
||||
// empty method
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
package com.sisvietnamvn.web.domain;
|
||||
|
||||
import static com.sisvietnamvn.web.domain.AuthorityTestSamples.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.sisvietnamvn.web.web.rest.TestUtil;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class AuthorityTest {
|
||||
|
||||
@Test
|
||||
void equalsVerifier() throws Exception {
|
||||
TestUtil.equalsVerifier(Authority.class);
|
||||
Authority authority1 = getAuthoritySample1();
|
||||
Authority authority2 = new Authority();
|
||||
assertThat(authority1).isNotEqualTo(authority2);
|
||||
|
||||
authority2.setName(authority1.getName());
|
||||
assertThat(authority1).isEqualTo(authority2);
|
||||
|
||||
authority2 = getAuthoritySample2();
|
||||
assertThat(authority1).isNotEqualTo(authority2);
|
||||
}
|
||||
|
||||
@Test
|
||||
void hashCodeVerifier() {
|
||||
Authority authority = new Authority();
|
||||
assertThat(authority.hashCode()).isZero();
|
||||
|
||||
Authority authority1 = getAuthoritySample1();
|
||||
authority.setName(authority1.getName());
|
||||
assertThat(authority).hasSameHashCodeAs(authority1);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package com.sisvietnamvn.web.domain;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class AuthorityTestSamples {
|
||||
|
||||
public static Authority getAuthoritySample1() {
|
||||
return new Authority().name("name1");
|
||||
}
|
||||
|
||||
public static Authority getAuthoritySample2() {
|
||||
return new Authority().name("name2");
|
||||
}
|
||||
|
||||
public static Authority getAuthorityRandomSampleGenerator() {
|
||||
return new Authority().name(UUID.randomUUID().toString());
|
||||
}
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package com.sisvietnamvn.web.management;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import java.util.Collection;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
class SecurityMetersServiceTests {
|
||||
|
||||
private static final String INVALID_TOKENS_METER_EXPECTED_NAME = "security.authentication.invalid-tokens";
|
||||
|
||||
private MeterRegistry meterRegistry;
|
||||
|
||||
private SecurityMetersService securityMetersService;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
meterRegistry = new SimpleMeterRegistry();
|
||||
|
||||
securityMetersService = new SecurityMetersService(meterRegistry);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInvalidTokensCountersByCauseAreCreated() {
|
||||
meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).counter();
|
||||
|
||||
meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "expired").counter();
|
||||
|
||||
meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "unsupported").counter();
|
||||
|
||||
meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "invalid-signature").counter();
|
||||
|
||||
meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "malformed").counter();
|
||||
|
||||
Collection<Counter> counters = meterRegistry.find(INVALID_TOKENS_METER_EXPECTED_NAME).counters();
|
||||
|
||||
assertThat(counters).hasSize(4);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCountMethodsShouldBeBoundToCorrectCounters() {
|
||||
assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "expired").counter().count()).isZero();
|
||||
|
||||
securityMetersService.trackTokenExpired();
|
||||
|
||||
assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "expired").counter().count()).isEqualTo(1);
|
||||
|
||||
assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "unsupported").counter().count()).isZero();
|
||||
|
||||
securityMetersService.trackTokenUnsupported();
|
||||
|
||||
assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "unsupported").counter().count()).isEqualTo(1);
|
||||
|
||||
assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "invalid-signature").counter().count()).isZero();
|
||||
|
||||
securityMetersService.trackTokenInvalidSignature();
|
||||
|
||||
assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "invalid-signature").counter().count()).isEqualTo(1);
|
||||
|
||||
assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "malformed").counter().count()).isZero();
|
||||
|
||||
securityMetersService.trackTokenMalformed();
|
||||
|
||||
assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "malformed").counter().count()).isEqualTo(1);
|
||||
}
|
||||
}
|
||||
+135
@@ -0,0 +1,135 @@
|
||||
package com.sisvietnamvn.web.repository.timezone;
|
||||
|
||||
import jakarta.persistence.*;
|
||||
import java.io.Serial;
|
||||
import java.io.Serializable;
|
||||
import java.time.*;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
@Table(name = "jhi_date_time_wrapper")
|
||||
public class DateTimeWrapper implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@Id
|
||||
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "sequenceGenerator")
|
||||
@SequenceGenerator(name = "sequenceGenerator")
|
||||
private Long id;
|
||||
|
||||
@Column(name = "instant")
|
||||
private Instant instant;
|
||||
|
||||
@Column(name = "local_date_time")
|
||||
private LocalDateTime localDateTime;
|
||||
|
||||
@Column(name = "offset_date_time")
|
||||
private OffsetDateTime offsetDateTime;
|
||||
|
||||
@Column(name = "zoned_date_time")
|
||||
private ZonedDateTime zonedDateTime;
|
||||
|
||||
@Column(name = "local_time")
|
||||
private LocalTime localTime;
|
||||
|
||||
@Column(name = "offset_time")
|
||||
private OffsetTime offsetTime;
|
||||
|
||||
@Column(name = "local_date")
|
||||
private LocalDate localDate;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Instant getInstant() {
|
||||
return instant;
|
||||
}
|
||||
|
||||
public void setInstant(Instant instant) {
|
||||
this.instant = instant;
|
||||
}
|
||||
|
||||
public LocalDateTime getLocalDateTime() {
|
||||
return localDateTime;
|
||||
}
|
||||
|
||||
public void setLocalDateTime(LocalDateTime localDateTime) {
|
||||
this.localDateTime = localDateTime;
|
||||
}
|
||||
|
||||
public OffsetDateTime getOffsetDateTime() {
|
||||
return offsetDateTime;
|
||||
}
|
||||
|
||||
public void setOffsetDateTime(OffsetDateTime offsetDateTime) {
|
||||
this.offsetDateTime = offsetDateTime;
|
||||
}
|
||||
|
||||
public ZonedDateTime getZonedDateTime() {
|
||||
return zonedDateTime;
|
||||
}
|
||||
|
||||
public void setZonedDateTime(ZonedDateTime zonedDateTime) {
|
||||
this.zonedDateTime = zonedDateTime;
|
||||
}
|
||||
|
||||
public LocalTime getLocalTime() {
|
||||
return localTime;
|
||||
}
|
||||
|
||||
public void setLocalTime(LocalTime localTime) {
|
||||
this.localTime = localTime;
|
||||
}
|
||||
|
||||
public OffsetTime getOffsetTime() {
|
||||
return offsetTime;
|
||||
}
|
||||
|
||||
public void setOffsetTime(OffsetTime offsetTime) {
|
||||
this.offsetTime = offsetTime;
|
||||
}
|
||||
|
||||
public LocalDate getLocalDate() {
|
||||
return localDate;
|
||||
}
|
||||
|
||||
public void setLocalDate(LocalDate localDate) {
|
||||
this.localDate = localDate;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DateTimeWrapper dateTimeWrapper = (DateTimeWrapper) o;
|
||||
return !(dateTimeWrapper.getId() == null || getId() == null) && Objects.equals(getId(), dateTimeWrapper.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(getId());
|
||||
}
|
||||
|
||||
// prettier-ignore
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TimeZoneTest{" +
|
||||
"id=" + id +
|
||||
", instant=" + instant +
|
||||
", localDateTime=" + localDateTime +
|
||||
", offsetDateTime=" + offsetDateTime +
|
||||
", zonedDateTime=" + zonedDateTime +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
package com.sisvietnamvn.web.repository.timezone;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.stereotype.Repository;
|
||||
|
||||
/**
|
||||
* Spring Data JPA repository for the {@link DateTimeWrapper} entity.
|
||||
*/
|
||||
@Repository
|
||||
public interface DateTimeWrapperRepository extends JpaRepository<DateTimeWrapper, Long> {}
|
||||
+136
@@ -0,0 +1,136 @@
|
||||
package com.sisvietnamvn.web.security;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
|
||||
import com.sisvietnamvn.web.IntegrationTest;
|
||||
import com.sisvietnamvn.web.domain.User;
|
||||
import com.sisvietnamvn.web.repository.UserRepository;
|
||||
import com.sisvietnamvn.web.service.UserService;
|
||||
import java.util.Locale;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integrations tests for {@link DomainUserDetailsService}.
|
||||
*/
|
||||
@Transactional
|
||||
@IntegrationTest
|
||||
class DomainUserDetailsServiceIT {
|
||||
|
||||
private static final String USER_ONE_LOGIN = "test-user-one";
|
||||
private static final String USER_ONE_EMAIL = "test-user-one@localhost";
|
||||
private static final String USER_TWO_LOGIN = "test-user-two";
|
||||
private static final String USER_TWO_EMAIL = "test-user-two@localhost";
|
||||
private static final String USER_THREE_LOGIN = "test-user-three";
|
||||
private static final String USER_THREE_EMAIL = "test-user-three@localhost";
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("userDetailsService")
|
||||
private UserDetailsService domainUserDetailsService;
|
||||
|
||||
public User getUserOne() {
|
||||
User userOne = new User();
|
||||
userOne.setLogin(USER_ONE_LOGIN);
|
||||
userOne.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
userOne.setActivated(true);
|
||||
userOne.setEmail(USER_ONE_EMAIL);
|
||||
userOne.setFirstName("userOne");
|
||||
userOne.setLastName("doe");
|
||||
userOne.setLangKey("en");
|
||||
return userOne;
|
||||
}
|
||||
|
||||
public User getUserTwo() {
|
||||
User userTwo = new User();
|
||||
userTwo.setLogin(USER_TWO_LOGIN);
|
||||
userTwo.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
userTwo.setActivated(true);
|
||||
userTwo.setEmail(USER_TWO_EMAIL);
|
||||
userTwo.setFirstName("userTwo");
|
||||
userTwo.setLastName("doe");
|
||||
userTwo.setLangKey("en");
|
||||
return userTwo;
|
||||
}
|
||||
|
||||
public User getUserThree() {
|
||||
User userThree = new User();
|
||||
userThree.setLogin(USER_THREE_LOGIN);
|
||||
userThree.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
userThree.setActivated(false);
|
||||
userThree.setEmail(USER_THREE_EMAIL);
|
||||
userThree.setFirstName("userThree");
|
||||
userThree.setLastName("doe");
|
||||
userThree.setLangKey("en");
|
||||
return userThree;
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void init() {
|
||||
userRepository.save(getUserOne());
|
||||
userRepository.save(getUserTwo());
|
||||
userRepository.save(getUserThree());
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanup() {
|
||||
userService.deleteUser(USER_ONE_LOGIN);
|
||||
userService.deleteUser(USER_TWO_LOGIN);
|
||||
userService.deleteUser(USER_THREE_LOGIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void assertThatUserCanBeFoundByLogin() {
|
||||
UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_ONE_LOGIN);
|
||||
assertThat(userDetails).isNotNull();
|
||||
assertThat(userDetails.getUsername()).isEqualTo(USER_ONE_LOGIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void assertThatUserCanBeFoundByLoginIgnoreCase() {
|
||||
UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_ONE_LOGIN.toUpperCase(Locale.ENGLISH));
|
||||
assertThat(userDetails).isNotNull();
|
||||
assertThat(userDetails.getUsername()).isEqualTo(USER_ONE_LOGIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void assertThatUserCanBeFoundByEmail() {
|
||||
UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_TWO_EMAIL);
|
||||
assertThat(userDetails).isNotNull();
|
||||
assertThat(userDetails.getUsername()).isEqualTo(USER_TWO_LOGIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void assertThatUserCanBeFoundByEmailIgnoreCase() {
|
||||
UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_TWO_EMAIL.toUpperCase(Locale.ENGLISH));
|
||||
assertThat(userDetails).isNotNull();
|
||||
assertThat(userDetails.getUsername()).isEqualTo(USER_TWO_LOGIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void assertThatEmailIsPrioritizedOverLogin() {
|
||||
UserDetails userDetails = domainUserDetailsService.loadUserByUsername(USER_ONE_EMAIL);
|
||||
assertThat(userDetails).isNotNull();
|
||||
assertThat(userDetails.getUsername()).isEqualTo(USER_ONE_LOGIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void assertThatUserNotActivatedExceptionIsThrownForNotActivatedUsers() {
|
||||
assertThatExceptionOfType(UserNotActivatedException.class).isThrownBy(() ->
|
||||
domainUserDetailsService.loadUserByUsername(USER_THREE_LOGIN)
|
||||
);
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
package com.sisvietnamvn.web.security;
|
||||
|
||||
import static com.sisvietnamvn.web.security.SecurityUtils.USER_ID_CLAIM;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.oauth2.jwt.Jwt;
|
||||
|
||||
/**
|
||||
* Test class for the {@link SecurityUtils} utility class.
|
||||
*/
|
||||
class SecurityUtilsUnitTest {
|
||||
|
||||
@BeforeEach
|
||||
@AfterEach
|
||||
void cleanup() {
|
||||
SecurityContextHolder.clearContext();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetCurrentUserLogin() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "admin"));
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
Optional<String> login = SecurityUtils.getCurrentUserLogin();
|
||||
assertThat(login).contains("admin");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetCurrentUserJWT() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "token"));
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
Optional<String> jwt = SecurityUtils.getCurrentUserJWT();
|
||||
assertThat(jwt).contains("token");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetCurrentUserJWTFromJwtCredentials() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
var now = Instant.now();
|
||||
var jwt = Jwt.withTokenValue("token").issuedAt(now).expiresAt(now.plusSeconds(60)).header("Test", "test").build();
|
||||
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("admin", jwt));
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
Optional<String> currentUserJwt = SecurityUtils.getCurrentUserJWT();
|
||||
assertThat(currentUserJwt).contains("token");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetCurrentUserId() {
|
||||
var userId = 1L;
|
||||
var securityContext = SecurityContextHolder.createEmptyContext();
|
||||
var now = Instant.now();
|
||||
var jwt = Jwt.withTokenValue("token")
|
||||
.issuedAt(now)
|
||||
.expiresAt(now.plusSeconds(60))
|
||||
.claim(USER_ID_CLAIM, userId)
|
||||
.header("Test", "test")
|
||||
.build();
|
||||
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken(jwt, "token"));
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
var contextUserId = SecurityUtils.getCurrentUserId();
|
||||
assertThat(contextUserId.orElse(null)).isEqualTo(userId);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testIsAuthenticated() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("admin", "admin"));
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
boolean isAuthenticated = SecurityUtils.isAuthenticated();
|
||||
assertThat(isAuthenticated).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAnonymousIsNotAuthenticated() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
var authorities = List.of(new SimpleGrantedAuthority(AuthoritiesConstants.ANONYMOUS));
|
||||
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("anonymous", "anonymous", authorities));
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
boolean isAuthenticated = SecurityUtils.isAuthenticated();
|
||||
assertThat(isAuthenticated).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHasCurrentUserThisAuthority() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
var authorities = List.of(new SimpleGrantedAuthority(AuthoritiesConstants.USER));
|
||||
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("anonymous", "anonymous", authorities));
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
|
||||
assertThat(SecurityUtils.hasCurrentUserThisAuthority(AuthoritiesConstants.USER)).isTrue();
|
||||
assertThat(SecurityUtils.hasCurrentUserThisAuthority(AuthoritiesConstants.ADMIN)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHasCurrentUserAnyOfAuthorities() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
var authorities = List.of(new SimpleGrantedAuthority(AuthoritiesConstants.USER));
|
||||
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("anonymous", "anonymous", authorities));
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
|
||||
assertThat(SecurityUtils.hasCurrentUserAnyOfAuthorities(AuthoritiesConstants.USER, AuthoritiesConstants.ADMIN)).isTrue();
|
||||
assertThat(SecurityUtils.hasCurrentUserAnyOfAuthorities(AuthoritiesConstants.ANONYMOUS, AuthoritiesConstants.ADMIN)).isFalse();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testHasCurrentUserNoneOfAuthorities() {
|
||||
SecurityContext securityContext = SecurityContextHolder.createEmptyContext();
|
||||
var authorities = List.of(new SimpleGrantedAuthority(AuthoritiesConstants.USER));
|
||||
securityContext.setAuthentication(new UsernamePasswordAuthenticationToken("anonymous", "anonymous", authorities));
|
||||
SecurityContextHolder.setContext(securityContext);
|
||||
|
||||
assertThat(SecurityUtils.hasCurrentUserNoneOfAuthorities(AuthoritiesConstants.USER, AuthoritiesConstants.ADMIN)).isFalse();
|
||||
assertThat(SecurityUtils.hasCurrentUserNoneOfAuthorities(AuthoritiesConstants.ANONYMOUS, AuthoritiesConstants.ADMIN)).isTrue();
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package com.sisvietnamvn.web.security.jwt;
|
||||
|
||||
import com.sisvietnamvn.web.config.SecurityConfiguration;
|
||||
import com.sisvietnamvn.web.config.SecurityJwtConfiguration;
|
||||
import com.sisvietnamvn.web.config.WebConfigurer;
|
||||
import com.sisvietnamvn.web.management.SecurityMetersService;
|
||||
import com.sisvietnamvn.web.web.rest.AuthenticateController;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import tech.jhipster.config.JHipsterProperties;
|
||||
|
||||
@Target(ElementType.TYPE)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@SpringBootTest(
|
||||
properties = {
|
||||
"jhipster.security.authentication.jwt.base64-secret=fd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8",
|
||||
"jhipster.security.authentication.jwt.token-validity-in-seconds=60000",
|
||||
},
|
||||
classes = {
|
||||
JHipsterProperties.class,
|
||||
WebConfigurer.class,
|
||||
SecurityConfiguration.class,
|
||||
SecurityJwtConfiguration.class,
|
||||
SecurityMetersService.class,
|
||||
AuthenticateController.class,
|
||||
JwtAuthenticationTestUtils.class,
|
||||
}
|
||||
)
|
||||
public @interface AuthenticationIntegrationTest {}
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
package com.sisvietnamvn.web.security.jwt;
|
||||
|
||||
import static com.sisvietnamvn.web.security.AuthoritiesConstants.ADMIN;
|
||||
import static com.sisvietnamvn.web.security.SecurityUtils.AUTHORITIES_CLAIM;
|
||||
import static com.sisvietnamvn.web.security.SecurityUtils.JWT_ALGORITHM;
|
||||
|
||||
import com.nimbusds.jose.jwk.source.ImmutableSecret;
|
||||
import com.nimbusds.jose.util.Base64;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
|
||||
import java.time.Instant;
|
||||
import java.util.List;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.security.crypto.codec.Hex;
|
||||
import org.springframework.security.oauth2.jwt.JwsHeader;
|
||||
import org.springframework.security.oauth2.jwt.JwtClaimsSet;
|
||||
import org.springframework.security.oauth2.jwt.JwtEncoder;
|
||||
import org.springframework.security.oauth2.jwt.JwtEncoderParameters;
|
||||
import org.springframework.security.oauth2.jwt.NimbusJwtEncoder;
|
||||
|
||||
public class JwtAuthenticationTestUtils {
|
||||
|
||||
public static final String BEARER = "Bearer ";
|
||||
|
||||
@Bean
|
||||
private MeterRegistry meterRegistry() {
|
||||
return new SimpleMeterRegistry();
|
||||
}
|
||||
|
||||
public static String createValidToken(String jwtKey) {
|
||||
return createValidTokenForUser(jwtKey, "anonymous");
|
||||
}
|
||||
|
||||
public static String createValidTokenForUser(String jwtKey, String user) {
|
||||
JwtEncoder encoder = jwtEncoder(jwtKey);
|
||||
|
||||
var now = Instant.now();
|
||||
|
||||
JwtClaimsSet claims = JwtClaimsSet.builder()
|
||||
.issuedAt(now)
|
||||
.expiresAt(now.plusSeconds(60))
|
||||
.subject(user)
|
||||
.claims(customClaim -> customClaim.put(AUTHORITIES_CLAIM, List.of(ADMIN)))
|
||||
.build();
|
||||
|
||||
JwsHeader jwsHeader = JwsHeader.with(JWT_ALGORITHM).build();
|
||||
return encoder.encode(JwtEncoderParameters.from(jwsHeader, claims)).getTokenValue();
|
||||
}
|
||||
|
||||
public static String createTokenWithDifferentSignature() {
|
||||
JwtEncoder encoder = jwtEncoder("Xfd54a45s65fds737b9aafcb3412e07ed99b267f33413274720ddbb7f6c5e64e9f14075f2d7ed041592f0b7657baf8");
|
||||
|
||||
var now = Instant.now();
|
||||
var past = now.plusSeconds(60);
|
||||
|
||||
JwtClaimsSet claims = JwtClaimsSet.builder().issuedAt(now).expiresAt(past).subject("anonymous").build();
|
||||
|
||||
JwsHeader jwsHeader = JwsHeader.with(JWT_ALGORITHM).build();
|
||||
return encoder.encode(JwtEncoderParameters.from(jwsHeader, claims)).getTokenValue();
|
||||
}
|
||||
|
||||
public static String createExpiredToken(String jwtKey) {
|
||||
JwtEncoder encoder = jwtEncoder(jwtKey);
|
||||
|
||||
var now = Instant.now();
|
||||
var past = now.minusSeconds(600);
|
||||
|
||||
JwtClaimsSet claims = JwtClaimsSet.builder().issuedAt(past).expiresAt(past.plusSeconds(1)).subject("anonymous").build();
|
||||
|
||||
JwsHeader jwsHeader = JwsHeader.with(JWT_ALGORITHM).build();
|
||||
return encoder.encode(JwtEncoderParameters.from(jwsHeader, claims)).getTokenValue();
|
||||
}
|
||||
|
||||
public static String createInvalidToken(String jwtKey) {
|
||||
return createValidToken(jwtKey).substring(1);
|
||||
}
|
||||
|
||||
public static String createSignedInvalidJwt(String jwtKey) throws Exception {
|
||||
return calculateHMAC("foo", jwtKey);
|
||||
}
|
||||
|
||||
private static JwtEncoder jwtEncoder(String jwtKey) {
|
||||
return new NimbusJwtEncoder(new ImmutableSecret<>(getSecretKey(jwtKey)));
|
||||
}
|
||||
|
||||
private static SecretKey getSecretKey(String jwtKey) {
|
||||
byte[] keyBytes = Base64.from(jwtKey).decode();
|
||||
return new SecretKeySpec(keyBytes, 0, keyBytes.length, JWT_ALGORITHM.getName());
|
||||
}
|
||||
|
||||
private static String calculateHMAC(String data, String key) throws Exception {
|
||||
SecretKeySpec secretKeySpec = new SecretKeySpec(Base64.from(key).decode(), "HmacSHA512");
|
||||
Mac mac = Mac.getInstance("HmacSHA512");
|
||||
mac.init(secretKeySpec);
|
||||
return String.copyValueOf(Hex.encode(mac.doFinal(data.getBytes())));
|
||||
}
|
||||
}
|
||||
+55
@@ -0,0 +1,55 @@
|
||||
package com.sisvietnamvn.web.security.jwt;
|
||||
|
||||
import static com.sisvietnamvn.web.security.jwt.JwtAuthenticationTestUtils.*;
|
||||
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
@AutoConfigureMockMvc
|
||||
@AuthenticationIntegrationTest
|
||||
class TokenAuthenticationIT {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
|
||||
@Value("${jhipster.security.authentication.jwt.base64-secret}")
|
||||
private String jwtKey;
|
||||
|
||||
@Test
|
||||
void testLoginWithValidToken() throws Exception {
|
||||
expectOk(createValidToken(jwtKey));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReturnFalseWhenJWThasInvalidSignature() throws Exception {
|
||||
expectUnauthorized(createTokenWithDifferentSignature());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReturnFalseWhenJWTisMalformed() throws Exception {
|
||||
expectUnauthorized(createSignedInvalidJwt(jwtKey));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testReturnFalseWhenJWTisExpired() throws Exception {
|
||||
expectUnauthorized(createExpiredToken(jwtKey));
|
||||
}
|
||||
|
||||
private void expectOk(String token) throws Exception {
|
||||
mvc.perform(MockMvcRequestBuilders.get("/api/authenticate").header(AUTHORIZATION, BEARER + token)).andExpect(
|
||||
status().isNoContent()
|
||||
);
|
||||
}
|
||||
|
||||
private void expectUnauthorized(String token) throws Exception {
|
||||
mvc.perform(MockMvcRequestBuilders.get("/api/authenticate").header(AUTHORIZATION, BEARER + token)).andExpect(
|
||||
status().isUnauthorized()
|
||||
);
|
||||
}
|
||||
}
|
||||
+88
@@ -0,0 +1,88 @@
|
||||
package com.sisvietnamvn.web.security.jwt;
|
||||
|
||||
import static com.sisvietnamvn.web.security.jwt.JwtAuthenticationTestUtils.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.http.HttpHeaders.AUTHORIZATION;
|
||||
|
||||
import io.micrometer.core.instrument.Counter;
|
||||
import io.micrometer.core.instrument.MeterRegistry;
|
||||
import java.util.Collection;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
|
||||
@AutoConfigureMockMvc
|
||||
@AuthenticationIntegrationTest
|
||||
class TokenAuthenticationSecurityMetersIT {
|
||||
|
||||
private static final String INVALID_TOKENS_METER_EXPECTED_NAME = "security.authentication.invalid-tokens";
|
||||
|
||||
@Autowired
|
||||
private MockMvc mvc;
|
||||
|
||||
@Value("${jhipster.security.authentication.jwt.base64-secret}")
|
||||
private String jwtKey;
|
||||
|
||||
@Autowired
|
||||
private MeterRegistry meterRegistry;
|
||||
|
||||
@Test
|
||||
void testValidTokenShouldNotCountAnything() throws Exception {
|
||||
Collection<Counter> counters = meterRegistry.find(INVALID_TOKENS_METER_EXPECTED_NAME).counters();
|
||||
|
||||
var count = aggregate(counters);
|
||||
|
||||
tryToAuthenticate(createValidToken(jwtKey));
|
||||
|
||||
assertThat(aggregate(counters)).isEqualTo(count);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTokenExpiredCount() throws Exception {
|
||||
var count = meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "expired").counter().count();
|
||||
|
||||
tryToAuthenticate(createExpiredToken(jwtKey));
|
||||
|
||||
assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "expired").counter().count()).isEqualTo(count + 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTokenSignatureInvalidCount() throws Exception {
|
||||
var count = meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "invalid-signature").counter().count();
|
||||
|
||||
tryToAuthenticate(createTokenWithDifferentSignature());
|
||||
|
||||
assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "invalid-signature").counter().count()).isEqualTo(
|
||||
count + 1
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTokenMalformedCount() throws Exception {
|
||||
var count = meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "malformed").counter().count();
|
||||
|
||||
tryToAuthenticate(createSignedInvalidJwt(jwtKey));
|
||||
|
||||
assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "malformed").counter().count()).isEqualTo(count + 1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testTokenInvalidCount() throws Exception {
|
||||
var count = meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "malformed").counter().count();
|
||||
|
||||
tryToAuthenticate(createInvalidToken(jwtKey));
|
||||
|
||||
assertThat(meterRegistry.get(INVALID_TOKENS_METER_EXPECTED_NAME).tag("cause", "malformed").counter().count()).isEqualTo(count + 1);
|
||||
}
|
||||
|
||||
private void tryToAuthenticate(String token) throws Exception {
|
||||
mvc.perform(MockMvcRequestBuilders.get("/api/authenticate").header(AUTHORIZATION, BEARER + token));
|
||||
}
|
||||
|
||||
private double aggregate(Collection<Counter> counters) {
|
||||
return counters.stream().mapToDouble(Counter::count).sum();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,239 @@
|
||||
package com.sisvietnamvn.web.service;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import com.sisvietnamvn.web.IntegrationTest;
|
||||
import com.sisvietnamvn.web.config.Constants;
|
||||
import com.sisvietnamvn.web.domain.User;
|
||||
import jakarta.mail.Multipart;
|
||||
import jakarta.mail.Session;
|
||||
import jakarta.mail.internet.MimeBodyPart;
|
||||
import jakarta.mail.internet.MimeMessage;
|
||||
import jakarta.mail.internet.MimeMultipart;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.junit.jupiter.MockitoExtension;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.mail.MailSendException;
|
||||
import org.springframework.mail.javamail.JavaMailSender;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
import tech.jhipster.config.JHipsterProperties;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link MailService}.
|
||||
*/
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
@IntegrationTest
|
||||
class MailServiceIT {
|
||||
|
||||
private static final String[] languages = {
|
||||
// jhipster-needle-i18n-language-constant-start
|
||||
// jhipster-needle-i18n-language-constant - JHipster will add/remove languages in this array
|
||||
};
|
||||
private static final Pattern PATTERN_LOCALE_3 = Pattern.compile("([a-z]{2})-([a-zA-Z]{4})-([a-z]{2})");
|
||||
private static final Pattern PATTERN_LOCALE_2 = Pattern.compile("([a-z]{2})-([a-z]{2})");
|
||||
|
||||
@Autowired
|
||||
private JHipsterProperties jHipsterProperties;
|
||||
|
||||
@MockitoBean
|
||||
private JavaMailSender javaMailSender;
|
||||
|
||||
@Captor
|
||||
private ArgumentCaptor<MimeMessage> messageCaptor;
|
||||
|
||||
@Autowired
|
||||
private MailService mailService;
|
||||
|
||||
@BeforeEach
|
||||
void setup() {
|
||||
doNothing().when(javaMailSender).send(any(MimeMessage.class));
|
||||
when(javaMailSender.createMimeMessage()).thenReturn(new MimeMessage((Session) null));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendEmail() throws Exception {
|
||||
mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", false, false);
|
||||
verify(javaMailSender).send(messageCaptor.capture());
|
||||
MimeMessage message = messageCaptor.getValue();
|
||||
assertThat(message.getSubject()).isEqualTo("testSubject");
|
||||
assertThat(message.getAllRecipients()[0]).hasToString("john.doe@example.com");
|
||||
assertThat(message.getFrom()[0]).hasToString(jHipsterProperties.getMail().getFrom());
|
||||
assertThat(message.getContent()).isInstanceOf(String.class);
|
||||
assertThat(message.getContent()).hasToString("testContent");
|
||||
assertThat(message.getDataHandler().getContentType()).isEqualTo("text/plain; charset=UTF-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendHtmlEmail() throws Exception {
|
||||
mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", false, true);
|
||||
verify(javaMailSender).send(messageCaptor.capture());
|
||||
MimeMessage message = messageCaptor.getValue();
|
||||
assertThat(message.getSubject()).isEqualTo("testSubject");
|
||||
assertThat(message.getAllRecipients()[0]).hasToString("john.doe@example.com");
|
||||
assertThat(message.getFrom()[0]).hasToString(jHipsterProperties.getMail().getFrom());
|
||||
assertThat(message.getContent()).isInstanceOf(String.class);
|
||||
assertThat(message.getContent()).hasToString("testContent");
|
||||
assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendMultipartEmail() throws Exception {
|
||||
mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", true, false);
|
||||
verify(javaMailSender).send(messageCaptor.capture());
|
||||
MimeMessage message = messageCaptor.getValue();
|
||||
MimeMultipart mp = (MimeMultipart) message.getContent();
|
||||
MimeBodyPart part = (MimeBodyPart) ((MimeMultipart) mp.getBodyPart(0).getContent()).getBodyPart(0);
|
||||
ByteArrayOutputStream aos = new ByteArrayOutputStream();
|
||||
part.writeTo(aos);
|
||||
assertThat(message.getSubject()).isEqualTo("testSubject");
|
||||
assertThat(message.getAllRecipients()[0]).hasToString("john.doe@example.com");
|
||||
assertThat(message.getFrom()[0]).hasToString(jHipsterProperties.getMail().getFrom());
|
||||
assertThat(message.getContent()).isInstanceOf(Multipart.class);
|
||||
assertThat(aos).hasToString("\r\ntestContent");
|
||||
assertThat(part.getDataHandler().getContentType()).isEqualTo("text/plain; charset=UTF-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendMultipartHtmlEmail() throws Exception {
|
||||
mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", true, true);
|
||||
verify(javaMailSender).send(messageCaptor.capture());
|
||||
MimeMessage message = messageCaptor.getValue();
|
||||
MimeMultipart mp = (MimeMultipart) message.getContent();
|
||||
MimeBodyPart part = (MimeBodyPart) ((MimeMultipart) mp.getBodyPart(0).getContent()).getBodyPart(0);
|
||||
ByteArrayOutputStream aos = new ByteArrayOutputStream();
|
||||
part.writeTo(aos);
|
||||
assertThat(message.getSubject()).isEqualTo("testSubject");
|
||||
assertThat(message.getAllRecipients()[0]).hasToString("john.doe@example.com");
|
||||
assertThat(message.getFrom()[0]).hasToString(jHipsterProperties.getMail().getFrom());
|
||||
assertThat(message.getContent()).isInstanceOf(Multipart.class);
|
||||
assertThat(aos).hasToString("\r\ntestContent");
|
||||
assertThat(part.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendEmailFromTemplate() throws Exception {
|
||||
User user = new User();
|
||||
user.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
user.setLogin("john");
|
||||
user.setEmail("john.doe@example.com");
|
||||
mailService.sendEmailFromTemplate(user, "mail/testEmail", "email.test.title");
|
||||
verify(javaMailSender).send(messageCaptor.capture());
|
||||
MimeMessage message = messageCaptor.getValue();
|
||||
assertThat(message.getSubject()).isEqualTo("test title");
|
||||
assertThat(message.getAllRecipients()[0]).hasToString(user.getEmail());
|
||||
assertThat(message.getFrom()[0]).hasToString(jHipsterProperties.getMail().getFrom());
|
||||
assertThat(message.getContent().toString()).isEqualToNormalizingNewlines("<html>test title, http://127.0.0.1:8080, john</html>\n");
|
||||
assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendActivationEmail() throws Exception {
|
||||
User user = new User();
|
||||
user.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
user.setLogin("john");
|
||||
user.setEmail("john.doe@example.com");
|
||||
mailService.sendActivationEmail(user);
|
||||
verify(javaMailSender).send(messageCaptor.capture());
|
||||
MimeMessage message = messageCaptor.getValue();
|
||||
assertThat(message.getAllRecipients()[0]).hasToString(user.getEmail());
|
||||
assertThat(message.getFrom()[0]).hasToString(jHipsterProperties.getMail().getFrom());
|
||||
assertThat(message.getContent().toString()).isNotEmpty();
|
||||
assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCreationEmail() throws Exception {
|
||||
User user = new User();
|
||||
user.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
user.setLogin("john");
|
||||
user.setEmail("john.doe@example.com");
|
||||
mailService.sendCreationEmail(user);
|
||||
verify(javaMailSender).send(messageCaptor.capture());
|
||||
MimeMessage message = messageCaptor.getValue();
|
||||
assertThat(message.getAllRecipients()[0]).hasToString(user.getEmail());
|
||||
assertThat(message.getFrom()[0]).hasToString(jHipsterProperties.getMail().getFrom());
|
||||
assertThat(message.getContent().toString()).isNotEmpty();
|
||||
assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendPasswordResetMail() throws Exception {
|
||||
User user = new User();
|
||||
user.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
user.setLogin("john");
|
||||
user.setEmail("john.doe@example.com");
|
||||
mailService.sendPasswordResetMail(user);
|
||||
verify(javaMailSender).send(messageCaptor.capture());
|
||||
MimeMessage message = messageCaptor.getValue();
|
||||
assertThat(message.getAllRecipients()[0]).hasToString(user.getEmail());
|
||||
assertThat(message.getFrom()[0]).hasToString(jHipsterProperties.getMail().getFrom());
|
||||
assertThat(message.getContent().toString()).isNotEmpty();
|
||||
assertThat(message.getDataHandler().getContentType()).isEqualTo("text/html;charset=UTF-8");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendEmailWithException() {
|
||||
doThrow(MailSendException.class).when(javaMailSender).send(any(MimeMessage.class));
|
||||
try {
|
||||
mailService.sendEmail("john.doe@example.com", "testSubject", "testContent", false, false);
|
||||
} catch (Exception e) {
|
||||
fail("Exception shouldn't have been thrown");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSendLocalizedEmailForAllSupportedLanguages() throws Exception {
|
||||
User user = new User();
|
||||
user.setLogin("john");
|
||||
user.setEmail("john.doe@example.com");
|
||||
for (String langKey : languages) {
|
||||
user.setLangKey(langKey);
|
||||
mailService.sendEmailFromTemplate(user, "mail/testEmail", "email.test.title");
|
||||
verify(javaMailSender, atLeastOnce()).send(messageCaptor.capture());
|
||||
MimeMessage message = messageCaptor.getValue();
|
||||
|
||||
String propertyFilePath = "i18n/messages_" + getMessageSourceSuffixForLanguage(langKey) + ".properties";
|
||||
URL resource = this.getClass().getClassLoader().getResource(propertyFilePath);
|
||||
Path filePath = Path.of(resource.toURI());
|
||||
Properties properties = new Properties();
|
||||
properties.load(new InputStreamReader(Files.newInputStream(filePath), Charset.forName("UTF-8")));
|
||||
|
||||
String emailTitle = (String) properties.get("email.test.title");
|
||||
assertThat(message.getSubject()).isEqualTo(emailTitle);
|
||||
assertThat(message.getContent().toString()).isEqualToNormalizingNewlines(
|
||||
"<html>" + emailTitle + ", http://127.0.0.1:8080, john</html>\n"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a lang key to the Java locale.
|
||||
*/
|
||||
private String getMessageSourceSuffixForLanguage(String langKey) {
|
||||
String javaLangKey = langKey;
|
||||
Matcher matcher2 = PATTERN_LOCALE_2.matcher(langKey);
|
||||
if (matcher2.matches()) {
|
||||
javaLangKey = matcher2.group(1) + "_" + matcher2.group(2).toUpperCase();
|
||||
}
|
||||
Matcher matcher3 = PATTERN_LOCALE_3.matcher(langKey);
|
||||
if (matcher3.matches()) {
|
||||
javaLangKey = matcher3.group(1) + "_" + matcher3.group(2) + "_" + matcher3.group(3).toUpperCase();
|
||||
}
|
||||
return javaLangKey;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,208 @@
|
||||
package com.sisvietnamvn.web.service;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import com.sisvietnamvn.web.IntegrationTest;
|
||||
import com.sisvietnamvn.web.domain.User;
|
||||
import com.sisvietnamvn.web.repository.UserRepository;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.data.auditing.AuditingHandler;
|
||||
import org.springframework.data.auditing.DateTimeProvider;
|
||||
import org.springframework.test.context.bean.override.mockito.MockitoBean;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import tech.jhipster.security.RandomUtil;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link UserService}.
|
||||
*/
|
||||
@IntegrationTest
|
||||
@Transactional
|
||||
class UserServiceIT {
|
||||
|
||||
private static final String DEFAULT_LOGIN = "johndoe_service";
|
||||
|
||||
private static final String DEFAULT_EMAIL = "johndoe_service@localhost";
|
||||
|
||||
private static final String DEFAULT_FIRSTNAME = "john";
|
||||
|
||||
private static final String DEFAULT_LASTNAME = "doe";
|
||||
|
||||
@Autowired
|
||||
private CacheManager cacheManager;
|
||||
|
||||
private static final String DEFAULT_IMAGEURL = "http://placehold.it/50x50";
|
||||
|
||||
private static final String DEFAULT_LANGKEY = "dummy";
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private AuditingHandler auditingHandler;
|
||||
|
||||
@MockitoBean
|
||||
private DateTimeProvider dateTimeProvider;
|
||||
|
||||
private User user;
|
||||
|
||||
private Long numberOfUsers;
|
||||
|
||||
@BeforeEach
|
||||
void countUsers() {
|
||||
numberOfUsers = userRepository.count();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void init() {
|
||||
user = new User();
|
||||
user.setLogin(DEFAULT_LOGIN);
|
||||
user.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
user.setActivated(true);
|
||||
user.setEmail(DEFAULT_EMAIL);
|
||||
user.setFirstName(DEFAULT_FIRSTNAME);
|
||||
user.setLastName(DEFAULT_LASTNAME);
|
||||
user.setImageUrl(DEFAULT_IMAGEURL);
|
||||
user.setLangKey(DEFAULT_LANGKEY);
|
||||
|
||||
when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.now()));
|
||||
auditingHandler.setDateTimeProvider(dateTimeProvider);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanupAndCheck() {
|
||||
cacheManager
|
||||
.getCacheNames()
|
||||
.stream()
|
||||
.map(cacheName -> this.cacheManager.getCache(cacheName))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(Cache::clear);
|
||||
userService.deleteUser(DEFAULT_LOGIN);
|
||||
assertThat(userRepository.count()).isEqualTo(numberOfUsers);
|
||||
numberOfUsers = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void assertThatUserMustExistToResetPassword() {
|
||||
userRepository.saveAndFlush(user);
|
||||
Optional<User> maybeUser = userService.requestPasswordReset("invalid.login@localhost");
|
||||
assertThat(maybeUser).isNotPresent();
|
||||
|
||||
maybeUser = userService.requestPasswordReset(user.getEmail());
|
||||
assertThat(maybeUser).isPresent();
|
||||
assertThat(maybeUser.orElse(null).getEmail()).isEqualTo(user.getEmail());
|
||||
assertThat(maybeUser.orElse(null).getResetDate()).isNotNull();
|
||||
assertThat(maybeUser.orElse(null).getResetKey()).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void assertThatOnlyActivatedUserCanRequestPasswordReset() {
|
||||
user.setActivated(false);
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
Optional<User> maybeUser = userService.requestPasswordReset(user.getLogin());
|
||||
assertThat(maybeUser).isNotPresent();
|
||||
userRepository.delete(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void assertThatResetKeyMustNotBeOlderThan24Hours() {
|
||||
Instant daysAgo = Instant.now().minus(25, ChronoUnit.HOURS);
|
||||
String resetKey = RandomUtil.generateResetKey();
|
||||
user.setActivated(true);
|
||||
user.setResetDate(daysAgo);
|
||||
user.setResetKey(resetKey);
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
Optional<User> maybeUser = userService.completePasswordReset("johndoe2", user.getResetKey());
|
||||
assertThat(maybeUser).isNotPresent();
|
||||
userRepository.delete(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void assertThatResetKeyMustBeValid() {
|
||||
Instant daysAgo = Instant.now().minus(25, ChronoUnit.HOURS);
|
||||
user.setActivated(true);
|
||||
user.setResetDate(daysAgo);
|
||||
user.setResetKey("1234");
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
Optional<User> maybeUser = userService.completePasswordReset("johndoe2", user.getResetKey());
|
||||
assertThat(maybeUser).isNotPresent();
|
||||
userRepository.delete(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void assertThatUserCanResetPassword() {
|
||||
String oldPassword = user.getPassword();
|
||||
Instant daysAgo = Instant.now().minus(2, ChronoUnit.HOURS);
|
||||
String resetKey = RandomUtil.generateResetKey();
|
||||
user.setActivated(true);
|
||||
user.setResetDate(daysAgo);
|
||||
user.setResetKey(resetKey);
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
Optional<User> maybeUser = userService.completePasswordReset("johndoe2", user.getResetKey());
|
||||
assertThat(maybeUser).isPresent();
|
||||
assertThat(maybeUser.orElse(null).getResetDate()).isNull();
|
||||
assertThat(maybeUser.orElse(null).getResetKey()).isNull();
|
||||
assertThat(maybeUser.orElse(null).getPassword()).isNotEqualTo(oldPassword);
|
||||
|
||||
userRepository.delete(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void assertThatNotActivatedUsersWithNotNullActivationKeyCreatedBefore3DaysAreDeleted() {
|
||||
Instant now = Instant.now();
|
||||
when(dateTimeProvider.getNow()).thenReturn(Optional.of(now.minus(4, ChronoUnit.DAYS)));
|
||||
user.setActivated(false);
|
||||
user.setActivationKey(RandomStringUtils.insecure().next(20));
|
||||
User dbUser = userRepository.saveAndFlush(user);
|
||||
dbUser.setCreatedDate(now.minus(4, ChronoUnit.DAYS));
|
||||
userRepository.saveAndFlush(user);
|
||||
Instant threeDaysAgo = now.minus(3, ChronoUnit.DAYS);
|
||||
List<User> users = userRepository.findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(threeDaysAgo);
|
||||
assertThat(users).isNotEmpty();
|
||||
userService.removeNotActivatedUsers();
|
||||
users = userRepository.findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(threeDaysAgo);
|
||||
assertThat(users).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void assertThatNotActivatedUsersWithNullActivationKeyCreatedBefore3DaysAreNotDeleted() {
|
||||
Instant now = Instant.now();
|
||||
when(dateTimeProvider.getNow()).thenReturn(Optional.of(now.minus(4, ChronoUnit.DAYS)));
|
||||
user.setActivated(false);
|
||||
User dbUser = userRepository.saveAndFlush(user);
|
||||
dbUser.setCreatedDate(now.minus(4, ChronoUnit.DAYS));
|
||||
userRepository.saveAndFlush(user);
|
||||
Instant threeDaysAgo = now.minus(3, ChronoUnit.DAYS);
|
||||
List<User> users = userRepository.findAllByActivatedIsFalseAndActivationKeyIsNotNullAndCreatedDateBefore(threeDaysAgo);
|
||||
assertThat(users).isEmpty();
|
||||
userService.removeNotActivatedUsers();
|
||||
Optional<User> maybeDbUser = userRepository.findById(dbUser.getId());
|
||||
assertThat(maybeDbUser).contains(dbUser);
|
||||
}
|
||||
}
|
||||
+179
@@ -0,0 +1,179 @@
|
||||
package com.sisvietnamvn.web.service.mapper;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import com.sisvietnamvn.web.domain.Authority;
|
||||
import com.sisvietnamvn.web.domain.User;
|
||||
import com.sisvietnamvn.web.security.AuthoritiesConstants;
|
||||
import com.sisvietnamvn.web.service.dto.AdminUserDTO;
|
||||
import com.sisvietnamvn.web.service.dto.UserDTO;
|
||||
import java.time.Instant;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link UserMapper}.
|
||||
*/
|
||||
class UserMapperTest {
|
||||
|
||||
private static final String DEFAULT_LOGIN = "johndoe";
|
||||
private static final Long DEFAULT_ID = 1L;
|
||||
|
||||
private UserMapper userMapper;
|
||||
private User user;
|
||||
private AdminUserDTO userDto;
|
||||
|
||||
@BeforeEach
|
||||
void init() {
|
||||
userMapper = new UserMapper();
|
||||
user = new User();
|
||||
user.setLogin(DEFAULT_LOGIN);
|
||||
user.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
user.setActivated(true);
|
||||
user.setEmail("johndoe@localhost");
|
||||
user.setFirstName("john");
|
||||
user.setLastName("doe");
|
||||
user.setImageUrl("image_url");
|
||||
user.setCreatedBy(DEFAULT_LOGIN);
|
||||
user.setCreatedDate(Instant.now());
|
||||
user.setLastModifiedBy(DEFAULT_LOGIN);
|
||||
user.setLastModifiedDate(Instant.now());
|
||||
user.setLangKey("en");
|
||||
|
||||
Set<Authority> authorities = new HashSet<>();
|
||||
Authority authority = new Authority();
|
||||
authority.setName(AuthoritiesConstants.USER);
|
||||
authorities.add(authority);
|
||||
user.setAuthorities(authorities);
|
||||
|
||||
userDto = new AdminUserDTO(user);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUserToUserDTO() {
|
||||
AdminUserDTO convertedUserDto = userMapper.userToAdminUserDTO(user);
|
||||
|
||||
assertThat(convertedUserDto.getId()).isEqualTo(user.getId());
|
||||
assertThat(convertedUserDto.getLogin()).isEqualTo(user.getLogin());
|
||||
assertThat(convertedUserDto.getFirstName()).isEqualTo(user.getFirstName());
|
||||
assertThat(convertedUserDto.getLastName()).isEqualTo(user.getLastName());
|
||||
assertThat(convertedUserDto.getEmail()).isEqualTo(user.getEmail());
|
||||
assertThat(convertedUserDto.isActivated()).isEqualTo(user.isActivated());
|
||||
assertThat(convertedUserDto.getImageUrl()).isEqualTo(user.getImageUrl());
|
||||
assertThat(convertedUserDto.getCreatedBy()).isEqualTo(user.getCreatedBy());
|
||||
assertThat(convertedUserDto.getCreatedDate()).isEqualTo(user.getCreatedDate());
|
||||
assertThat(convertedUserDto.getLastModifiedBy()).isEqualTo(user.getLastModifiedBy());
|
||||
assertThat(convertedUserDto.getLastModifiedDate()).isEqualTo(user.getLastModifiedDate());
|
||||
assertThat(convertedUserDto.getLangKey()).isEqualTo(user.getLangKey());
|
||||
assertThat(convertedUserDto.getAuthorities()).containsExactly(AuthoritiesConstants.USER);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUserDTOtoUser() {
|
||||
User convertedUser = userMapper.userDTOToUser(userDto);
|
||||
|
||||
assertThat(convertedUser.getId()).isEqualTo(userDto.getId());
|
||||
assertThat(convertedUser.getLogin()).isEqualTo(userDto.getLogin());
|
||||
assertThat(convertedUser.getFirstName()).isEqualTo(userDto.getFirstName());
|
||||
assertThat(convertedUser.getLastName()).isEqualTo(userDto.getLastName());
|
||||
assertThat(convertedUser.getEmail()).isEqualTo(userDto.getEmail());
|
||||
assertThat(convertedUser.isActivated()).isEqualTo(userDto.isActivated());
|
||||
assertThat(convertedUser.getImageUrl()).isEqualTo(userDto.getImageUrl());
|
||||
assertThat(convertedUser.getLangKey()).isEqualTo(userDto.getLangKey());
|
||||
assertThat(convertedUser.getCreatedBy()).isEqualTo(userDto.getCreatedBy());
|
||||
assertThat(convertedUser.getCreatedDate()).isEqualTo(userDto.getCreatedDate());
|
||||
assertThat(convertedUser.getLastModifiedBy()).isEqualTo(userDto.getLastModifiedBy());
|
||||
assertThat(convertedUser.getLastModifiedDate()).isEqualTo(userDto.getLastModifiedDate());
|
||||
assertThat(convertedUser.getAuthorities()).extracting("name").containsExactly(AuthoritiesConstants.USER);
|
||||
}
|
||||
|
||||
@Test
|
||||
void usersToUserDTOsShouldMapOnlyNonNullUsers() {
|
||||
List<User> users = new ArrayList<>();
|
||||
users.add(user);
|
||||
users.add(null);
|
||||
|
||||
List<UserDTO> userDTOS = userMapper.usersToUserDTOs(users);
|
||||
|
||||
assertThat(userDTOS).isNotEmpty().size().isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void userDTOsToUsersShouldMapOnlyNonNullUsers() {
|
||||
List<AdminUserDTO> usersDto = new ArrayList<>();
|
||||
usersDto.add(userDto);
|
||||
usersDto.add(null);
|
||||
|
||||
List<User> users = userMapper.userDTOsToUsers(usersDto);
|
||||
|
||||
assertThat(users).isNotEmpty().size().isEqualTo(1);
|
||||
}
|
||||
|
||||
@Test
|
||||
void userDTOsToUsersWithAuthoritiesStringShouldMapToUsersWithAuthoritiesDomain() {
|
||||
Set<String> authoritiesAsString = new HashSet<>();
|
||||
authoritiesAsString.add("ADMIN");
|
||||
userDto.setAuthorities(authoritiesAsString);
|
||||
|
||||
List<AdminUserDTO> usersDto = new ArrayList<>();
|
||||
usersDto.add(userDto);
|
||||
|
||||
List<User> users = userMapper.userDTOsToUsers(usersDto);
|
||||
|
||||
assertThat(users).isNotEmpty().size().isEqualTo(1);
|
||||
assertThat(users.getFirst().getAuthorities()).isNotNull();
|
||||
assertThat(users.getFirst().getAuthorities()).isNotEmpty();
|
||||
assertThat(users.getFirst().getAuthorities().iterator().next().getName()).isEqualTo("ADMIN");
|
||||
}
|
||||
|
||||
@Test
|
||||
void userDTOsToUsersMapWithNullAuthoritiesStringShouldReturnUserWithEmptyAuthorities() {
|
||||
userDto.setAuthorities(null);
|
||||
|
||||
List<AdminUserDTO> usersDto = new ArrayList<>();
|
||||
usersDto.add(userDto);
|
||||
|
||||
List<User> users = userMapper.userDTOsToUsers(usersDto);
|
||||
|
||||
assertThat(users).isNotEmpty().size().isEqualTo(1);
|
||||
assertThat(users.getFirst().getAuthorities()).isNotNull();
|
||||
assertThat(users.getFirst().getAuthorities()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void userDTOToUserMapWithAuthoritiesStringShouldReturnUserWithAuthorities() {
|
||||
User convertedUser = userMapper.userDTOToUser(userDto);
|
||||
|
||||
assertThat(convertedUser).isNotNull();
|
||||
assertThat(convertedUser.getAuthorities()).isNotNull();
|
||||
assertThat(convertedUser.getAuthorities()).isNotEmpty();
|
||||
assertThat(convertedUser.getAuthorities().iterator().next().getName()).isEqualTo(AuthoritiesConstants.USER);
|
||||
}
|
||||
|
||||
@Test
|
||||
void userDTOToUserMapWithNullAuthoritiesStringShouldReturnUserWithEmptyAuthorities() {
|
||||
userDto.setAuthorities(null);
|
||||
|
||||
User persistUser = userMapper.userDTOToUser(userDto);
|
||||
|
||||
assertThat(persistUser).isNotNull();
|
||||
assertThat(persistUser.getAuthorities()).isNotNull();
|
||||
assertThat(persistUser.getAuthorities()).isEmpty();
|
||||
}
|
||||
|
||||
@Test
|
||||
void userDTOToUserMapWithNullUserShouldReturnNull() {
|
||||
assertThat(userMapper.userDTOToUser(null)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUserFromId() {
|
||||
assertThat(userMapper.userFromId(DEFAULT_ID).getId()).isEqualTo(DEFAULT_ID);
|
||||
assertThat(userMapper.userFromId(null)).isNull();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,778 @@
|
||||
package com.sisvietnamvn.web.web.rest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.sisvietnamvn.web.IntegrationTest;
|
||||
import com.sisvietnamvn.web.config.Constants;
|
||||
import com.sisvietnamvn.web.domain.User;
|
||||
import com.sisvietnamvn.web.repository.AuthorityRepository;
|
||||
import com.sisvietnamvn.web.repository.UserRepository;
|
||||
import com.sisvietnamvn.web.security.AuthoritiesConstants;
|
||||
import com.sisvietnamvn.web.service.UserService;
|
||||
import com.sisvietnamvn.web.service.dto.AdminUserDTO;
|
||||
import com.sisvietnamvn.web.service.dto.PasswordChangeDTO;
|
||||
import com.sisvietnamvn.web.web.rest.vm.KeyAndPasswordVM;
|
||||
import com.sisvietnamvn.web.web.rest.vm.ManagedUserVM;
|
||||
import java.time.Instant;
|
||||
import java.util.*;
|
||||
import java.util.stream.Stream;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link AccountResource} REST controller.
|
||||
*/
|
||||
@AutoConfigureMockMvc
|
||||
@IntegrationTest
|
||||
class AccountResourceIT {
|
||||
|
||||
static final String TEST_USER_LOGIN = "test";
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper om;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private AuthorityRepository authorityRepository;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Autowired
|
||||
private MockMvc restAccountMockMvc;
|
||||
|
||||
private Long numberOfUsers;
|
||||
|
||||
@BeforeEach
|
||||
void countUsers() {
|
||||
numberOfUsers = userRepository.count();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanupAndCheck() {
|
||||
assertThat(userRepository.count()).isEqualTo(numberOfUsers);
|
||||
numberOfUsers = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithUnauthenticatedMockUser
|
||||
void testNonAuthenticatedUser() throws Exception {
|
||||
restAccountMockMvc.perform(get("/api/authenticate")).andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(TEST_USER_LOGIN)
|
||||
void testAuthenticatedUser() throws Exception {
|
||||
restAccountMockMvc.perform(get("/api/authenticate").with(request -> request)).andExpect(status().isNoContent());
|
||||
}
|
||||
|
||||
@Test
|
||||
@WithMockUser(TEST_USER_LOGIN)
|
||||
void testGetExistingAccount() throws Exception {
|
||||
Set<String> authorities = new HashSet<>();
|
||||
authorities.add(AuthoritiesConstants.ADMIN);
|
||||
|
||||
AdminUserDTO user = new AdminUserDTO();
|
||||
user.setLogin(TEST_USER_LOGIN);
|
||||
user.setFirstName("john");
|
||||
user.setLastName("doe");
|
||||
user.setEmail("john.doe@jhipster.com");
|
||||
user.setImageUrl("http://placehold.it/50x50");
|
||||
user.setLangKey("en");
|
||||
user.setAuthorities(authorities);
|
||||
userService.createUser(user);
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(get("/api/account").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.login").value(TEST_USER_LOGIN))
|
||||
.andExpect(jsonPath("$.firstName").value("john"))
|
||||
.andExpect(jsonPath("$.lastName").value("doe"))
|
||||
.andExpect(jsonPath("$.email").value("john.doe@jhipster.com"))
|
||||
.andExpect(jsonPath("$.imageUrl").value("http://placehold.it/50x50"))
|
||||
.andExpect(jsonPath("$.langKey").value("en"))
|
||||
.andExpect(jsonPath("$.authorities").value(AuthoritiesConstants.ADMIN));
|
||||
|
||||
userService.deleteUser(TEST_USER_LOGIN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testGetUnknownAccount() throws Exception {
|
||||
restAccountMockMvc.perform(get("/api/account").accept(MediaType.APPLICATION_PROBLEM_JSON)).andExpect(status().isUnauthorized());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testRegisterValid() throws Exception {
|
||||
ManagedUserVM validUser = new ManagedUserVM();
|
||||
validUser.setLogin("test-register-valid");
|
||||
validUser.setPassword("password");
|
||||
validUser.setFirstName("Alice");
|
||||
validUser.setLastName("Test");
|
||||
validUser.setEmail("test-register-valid@example.com");
|
||||
validUser.setImageUrl("http://placehold.it/50x50");
|
||||
validUser.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
validUser.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
assertThat(userRepository.findOneByLogin("test-register-valid")).isEmpty();
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/register").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(validUser)))
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
assertThat(userRepository.findOneByLogin("test-register-valid")).isPresent();
|
||||
|
||||
userService.deleteUser("test-register-valid");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testRegisterInvalidLogin() throws Exception {
|
||||
ManagedUserVM invalidUser = new ManagedUserVM();
|
||||
invalidUser.setLogin("funky-log(n"); // <-- invalid
|
||||
invalidUser.setPassword("password");
|
||||
invalidUser.setFirstName("Funky");
|
||||
invalidUser.setLastName("One");
|
||||
invalidUser.setEmail("funky@example.com");
|
||||
invalidUser.setActivated(true);
|
||||
invalidUser.setImageUrl("http://placehold.it/50x50");
|
||||
invalidUser.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
invalidUser.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/register").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(invalidUser)))
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
Optional<User> user = userRepository.findOneByEmailIgnoreCase("funky@example.com");
|
||||
assertThat(user).isEmpty();
|
||||
}
|
||||
|
||||
static Stream<ManagedUserVM> invalidUsers() {
|
||||
return Stream.of(
|
||||
createInvalidUser("bob", "password", "Bob", "Green", "invalid", true), // <-- invalid
|
||||
createInvalidUser("bob", "123", "Bob", "Green", "bob@example.com", true), // password with only 3 digits
|
||||
createInvalidUser("bob", null, "Bob", "Green", "bob@example.com", true) // invalid null password
|
||||
);
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("invalidUsers")
|
||||
@Transactional
|
||||
void testRegisterInvalidUsers(ManagedUserVM invalidUser) throws Exception {
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/register").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(invalidUser)))
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
Optional<User> user = userRepository.findOneByLogin("bob");
|
||||
assertThat(user).isEmpty();
|
||||
}
|
||||
|
||||
private static ManagedUserVM createInvalidUser(
|
||||
String login,
|
||||
String password,
|
||||
String firstName,
|
||||
String lastName,
|
||||
String email,
|
||||
boolean activated
|
||||
) {
|
||||
ManagedUserVM invalidUser = new ManagedUserVM();
|
||||
invalidUser.setLogin(login);
|
||||
invalidUser.setPassword(password);
|
||||
invalidUser.setFirstName(firstName);
|
||||
invalidUser.setLastName(lastName);
|
||||
invalidUser.setEmail(email);
|
||||
invalidUser.setActivated(activated);
|
||||
invalidUser.setImageUrl("http://placehold.it/50x50");
|
||||
invalidUser.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
invalidUser.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
return invalidUser;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testRegisterDuplicateLogin() throws Exception {
|
||||
// First registration
|
||||
ManagedUserVM firstUser = new ManagedUserVM();
|
||||
firstUser.setLogin("alice");
|
||||
firstUser.setPassword("password");
|
||||
firstUser.setFirstName("Alice");
|
||||
firstUser.setLastName("Something");
|
||||
firstUser.setEmail("alice@example.com");
|
||||
firstUser.setImageUrl("http://placehold.it/50x50");
|
||||
firstUser.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
firstUser.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
|
||||
// Duplicate login, different email
|
||||
ManagedUserVM secondUser = new ManagedUserVM();
|
||||
secondUser.setLogin(firstUser.getLogin());
|
||||
secondUser.setPassword(firstUser.getPassword());
|
||||
secondUser.setFirstName(firstUser.getFirstName());
|
||||
secondUser.setLastName(firstUser.getLastName());
|
||||
secondUser.setEmail("alice2@example.com");
|
||||
secondUser.setImageUrl(firstUser.getImageUrl());
|
||||
secondUser.setLangKey(firstUser.getLangKey());
|
||||
secondUser.setCreatedBy(firstUser.getCreatedBy());
|
||||
secondUser.setCreatedDate(firstUser.getCreatedDate());
|
||||
secondUser.setLastModifiedBy(firstUser.getLastModifiedBy());
|
||||
secondUser.setLastModifiedDate(firstUser.getLastModifiedDate());
|
||||
secondUser.setAuthorities(new HashSet<>(firstUser.getAuthorities()));
|
||||
|
||||
// First user
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/register").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(firstUser)))
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
// Second (non activated) user
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/register").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(secondUser)))
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
Optional<User> testUser = userRepository.findOneByEmailIgnoreCase("alice2@example.com");
|
||||
assertThat(testUser).isPresent();
|
||||
testUser.orElseThrow().setActivated(true);
|
||||
userRepository.save(testUser.orElseThrow());
|
||||
|
||||
// Second (already activated) user
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/register").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(secondUser)))
|
||||
.andExpect(status().is4xxClientError());
|
||||
|
||||
userService.deleteUser("alice");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testRegisterDuplicateEmail() throws Exception {
|
||||
// First user
|
||||
ManagedUserVM firstUser = new ManagedUserVM();
|
||||
firstUser.setLogin("test-register-duplicate-email");
|
||||
firstUser.setPassword("password");
|
||||
firstUser.setFirstName("Alice");
|
||||
firstUser.setLastName("Test");
|
||||
firstUser.setEmail("test-register-duplicate-email@example.com");
|
||||
firstUser.setImageUrl("http://placehold.it/50x50");
|
||||
firstUser.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
firstUser.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
|
||||
// Register first user
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/register").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(firstUser)))
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
Optional<User> testUser1 = userRepository.findOneByLogin("test-register-duplicate-email");
|
||||
assertThat(testUser1).isPresent();
|
||||
|
||||
// Duplicate email, different login
|
||||
ManagedUserVM secondUser = new ManagedUserVM();
|
||||
secondUser.setLogin("test-register-duplicate-email-2");
|
||||
secondUser.setPassword(firstUser.getPassword());
|
||||
secondUser.setFirstName(firstUser.getFirstName());
|
||||
secondUser.setLastName(firstUser.getLastName());
|
||||
secondUser.setEmail(firstUser.getEmail());
|
||||
secondUser.setImageUrl(firstUser.getImageUrl());
|
||||
secondUser.setLangKey(firstUser.getLangKey());
|
||||
secondUser.setAuthorities(new HashSet<>(firstUser.getAuthorities()));
|
||||
|
||||
// Register second (non activated) user
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/register").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(secondUser)))
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
Optional<User> testUser2 = userRepository.findOneByLogin("test-register-duplicate-email");
|
||||
assertThat(testUser2).isEmpty();
|
||||
|
||||
Optional<User> testUser3 = userRepository.findOneByLogin("test-register-duplicate-email-2");
|
||||
assertThat(testUser3).isPresent();
|
||||
|
||||
// Duplicate email - with uppercase email address
|
||||
ManagedUserVM userWithUpperCaseEmail = new ManagedUserVM();
|
||||
userWithUpperCaseEmail.setId(firstUser.getId());
|
||||
userWithUpperCaseEmail.setLogin("test-register-duplicate-email-3");
|
||||
userWithUpperCaseEmail.setPassword(firstUser.getPassword());
|
||||
userWithUpperCaseEmail.setFirstName(firstUser.getFirstName());
|
||||
userWithUpperCaseEmail.setLastName(firstUser.getLastName());
|
||||
userWithUpperCaseEmail.setEmail("TEST-register-duplicate-email@example.com");
|
||||
userWithUpperCaseEmail.setImageUrl(firstUser.getImageUrl());
|
||||
userWithUpperCaseEmail.setLangKey(firstUser.getLangKey());
|
||||
userWithUpperCaseEmail.setAuthorities(new HashSet<>(firstUser.getAuthorities()));
|
||||
|
||||
// Register third (not activated) user
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/register").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userWithUpperCaseEmail)))
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
Optional<User> testUser4 = userRepository.findOneByLogin("test-register-duplicate-email-3");
|
||||
assertThat(testUser4).isPresent();
|
||||
assertThat(testUser4.orElseThrow().getEmail()).isEqualTo("test-register-duplicate-email@example.com");
|
||||
|
||||
testUser4.orElseThrow().setActivated(true);
|
||||
userService.updateUser((new AdminUserDTO(testUser4.orElseThrow())));
|
||||
|
||||
// Register 4th (already activated) user
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/register").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(secondUser)))
|
||||
.andExpect(status().is4xxClientError());
|
||||
|
||||
userService.deleteUser("test-register-duplicate-email-3");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testRegisterAdminIsIgnored() throws Exception {
|
||||
ManagedUserVM validUser = new ManagedUserVM();
|
||||
validUser.setLogin("badguy");
|
||||
validUser.setPassword("password");
|
||||
validUser.setFirstName("Bad");
|
||||
validUser.setLastName("Guy");
|
||||
validUser.setEmail("badguy@example.com");
|
||||
validUser.setActivated(true);
|
||||
validUser.setImageUrl("http://placehold.it/50x50");
|
||||
validUser.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
validUser.setAuthorities(Set.of(AuthoritiesConstants.ADMIN));
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/register").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(validUser)))
|
||||
.andExpect(status().isCreated());
|
||||
|
||||
Optional<User> userDup = userRepository.findOneWithAuthoritiesByLogin("badguy");
|
||||
assertThat(userDup).isPresent();
|
||||
assertThat(userDup.orElseThrow().getAuthorities())
|
||||
.hasSize(1)
|
||||
.containsExactly(authorityRepository.findById(AuthoritiesConstants.USER).orElseThrow());
|
||||
|
||||
userService.deleteUser("badguy");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testActivateAccount() throws Exception {
|
||||
final String activationKey = "some activation key";
|
||||
User user = new User();
|
||||
user.setLogin("activate-account");
|
||||
user.setEmail("activate-account@example.com");
|
||||
user.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
user.setActivated(false);
|
||||
user.setActivationKey(activationKey);
|
||||
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
restAccountMockMvc.perform(get("/api/activate?key={activationKey}", activationKey)).andExpect(status().isOk());
|
||||
|
||||
user = userRepository.findOneByLogin(user.getLogin()).orElse(null);
|
||||
assertThat(user.isActivated()).isTrue();
|
||||
|
||||
userService.deleteUser("activate-account");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testActivateAccountWithWrongKey() throws Exception {
|
||||
restAccountMockMvc.perform(get("/api/activate?key=wrongActivationKey")).andExpect(status().isInternalServerError());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@WithMockUser("save-account")
|
||||
void testSaveAccount() throws Exception {
|
||||
User user = new User();
|
||||
user.setLogin("save-account");
|
||||
user.setEmail("save-account@example.com");
|
||||
user.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
user.setActivated(true);
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
AdminUserDTO userDTO = new AdminUserDTO();
|
||||
userDTO.setLogin("not-used");
|
||||
userDTO.setFirstName("firstname");
|
||||
userDTO.setLastName("lastname");
|
||||
userDTO.setEmail("save-account@example.com");
|
||||
userDTO.setActivated(false);
|
||||
userDTO.setImageUrl("http://placehold.it/50x50");
|
||||
userDTO.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
userDTO.setAuthorities(Set.of(AuthoritiesConstants.ADMIN));
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/account").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userDTO)))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
User updatedUser = userRepository.findOneWithAuthoritiesByLogin(user.getLogin()).orElse(null);
|
||||
assertThat(updatedUser.getFirstName()).isEqualTo(userDTO.getFirstName());
|
||||
assertThat(updatedUser.getLastName()).isEqualTo(userDTO.getLastName());
|
||||
assertThat(updatedUser.getEmail()).isEqualTo(userDTO.getEmail());
|
||||
assertThat(updatedUser.getLangKey()).isEqualTo(userDTO.getLangKey());
|
||||
assertThat(updatedUser.getPassword()).isEqualTo(user.getPassword());
|
||||
assertThat(updatedUser.getImageUrl()).isEqualTo(userDTO.getImageUrl());
|
||||
assertThat(updatedUser.isActivated()).isTrue();
|
||||
assertThat(updatedUser.getAuthorities()).isEmpty();
|
||||
|
||||
userService.deleteUser("save-account");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@WithMockUser("save-invalid-email")
|
||||
void testSaveInvalidEmail() throws Exception {
|
||||
User user = new User();
|
||||
user.setLogin("save-invalid-email");
|
||||
user.setEmail("save-invalid-email@example.com");
|
||||
user.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
user.setActivated(true);
|
||||
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
AdminUserDTO userDTO = new AdminUserDTO();
|
||||
userDTO.setLogin("not-used");
|
||||
userDTO.setFirstName("firstname");
|
||||
userDTO.setLastName("lastname");
|
||||
userDTO.setEmail("invalid email");
|
||||
userDTO.setActivated(false);
|
||||
userDTO.setImageUrl("http://placehold.it/50x50");
|
||||
userDTO.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
userDTO.setAuthorities(Set.of(AuthoritiesConstants.ADMIN));
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/account").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userDTO)))
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
assertThat(userRepository.findOneByEmailIgnoreCase("invalid email")).isNotPresent();
|
||||
|
||||
userService.deleteUser("save-invalid-email");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@WithMockUser("save-existing-email")
|
||||
void testSaveExistingEmail() throws Exception {
|
||||
User user = new User();
|
||||
user.setLogin("save-existing-email");
|
||||
user.setEmail("save-existing-email@example.com");
|
||||
user.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
user.setActivated(true);
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
User anotherUser = new User();
|
||||
anotherUser.setLogin("save-existing-email2");
|
||||
anotherUser.setEmail("save-existing-email2@example.com");
|
||||
anotherUser.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
anotherUser.setActivated(true);
|
||||
|
||||
userRepository.saveAndFlush(anotherUser);
|
||||
|
||||
AdminUserDTO userDTO = new AdminUserDTO();
|
||||
userDTO.setLogin("not-used");
|
||||
userDTO.setFirstName("firstname");
|
||||
userDTO.setLastName("lastname");
|
||||
userDTO.setEmail("save-existing-email2@example.com");
|
||||
userDTO.setActivated(false);
|
||||
userDTO.setImageUrl("http://placehold.it/50x50");
|
||||
userDTO.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
userDTO.setAuthorities(Set.of(AuthoritiesConstants.ADMIN));
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/account").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userDTO)))
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
User updatedUser = userRepository.findOneByLogin("save-existing-email").orElseThrow();
|
||||
assertThat(updatedUser.getEmail()).isEqualTo("save-existing-email@example.com");
|
||||
|
||||
userService.deleteUser("save-existing-email");
|
||||
userService.deleteUser("save-existing-email2");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@WithMockUser("save-existing-email-and-login")
|
||||
void testSaveExistingEmailAndLogin() throws Exception {
|
||||
User user = new User();
|
||||
user.setLogin("save-existing-email-and-login");
|
||||
user.setEmail("save-existing-email-and-login@example.com");
|
||||
user.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
user.setActivated(true);
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
AdminUserDTO userDTO = new AdminUserDTO();
|
||||
userDTO.setLogin("not-used");
|
||||
userDTO.setFirstName("firstname");
|
||||
userDTO.setLastName("lastname");
|
||||
userDTO.setEmail("save-existing-email-and-login@example.com");
|
||||
userDTO.setActivated(false);
|
||||
userDTO.setImageUrl("http://placehold.it/50x50");
|
||||
userDTO.setLangKey(Constants.DEFAULT_LANGUAGE);
|
||||
userDTO.setAuthorities(Set.of(AuthoritiesConstants.ADMIN));
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/account").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userDTO)))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
User updatedUser = userRepository.findOneByLogin("save-existing-email-and-login").orElse(null);
|
||||
assertThat(updatedUser.getEmail()).isEqualTo("save-existing-email-and-login@example.com");
|
||||
|
||||
userService.deleteUser("save-existing-email-and-login");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@WithMockUser("change-password-wrong-existing-password")
|
||||
void testChangePasswordWrongExistingPassword() throws Exception {
|
||||
User user = new User();
|
||||
String currentPassword = RandomStringUtils.insecure().nextAlphanumeric(60);
|
||||
user.setPassword(passwordEncoder.encode(currentPassword));
|
||||
user.setLogin("change-password-wrong-existing-password");
|
||||
user.setEmail("change-password-wrong-existing-password@example.com");
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(
|
||||
post("/api/account/change-password")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(om.writeValueAsBytes(new PasswordChangeDTO("1" + currentPassword, "new password")))
|
||||
)
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
User updatedUser = userRepository.findOneByLogin("change-password-wrong-existing-password").orElse(null);
|
||||
assertThat(passwordEncoder.matches("new password", updatedUser.getPassword())).isFalse();
|
||||
assertThat(passwordEncoder.matches(currentPassword, updatedUser.getPassword())).isTrue();
|
||||
|
||||
userService.deleteUser("change-password-wrong-existing-password");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@WithMockUser("change-password")
|
||||
void testChangePassword() throws Exception {
|
||||
User user = new User();
|
||||
String currentPassword = RandomStringUtils.insecure().nextAlphanumeric(60);
|
||||
user.setPassword(passwordEncoder.encode(currentPassword));
|
||||
user.setLogin("change-password");
|
||||
user.setEmail("change-password@example.com");
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(
|
||||
post("/api/account/change-password")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(om.writeValueAsBytes(new PasswordChangeDTO(currentPassword, "new password")))
|
||||
)
|
||||
.andExpect(status().isOk());
|
||||
|
||||
User updatedUser = userRepository.findOneByLogin("change-password").orElse(null);
|
||||
assertThat(passwordEncoder.matches("new password", updatedUser.getPassword())).isTrue();
|
||||
|
||||
userService.deleteUser("change-password");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@WithMockUser("change-password-too-small")
|
||||
void testChangePasswordTooSmall() throws Exception {
|
||||
User user = new User();
|
||||
String currentPassword = RandomStringUtils.insecure().nextAlphanumeric(60);
|
||||
user.setPassword(passwordEncoder.encode(currentPassword));
|
||||
user.setLogin("change-password-too-small");
|
||||
user.setEmail("change-password-too-small@example.com");
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
String newPassword = RandomStringUtils.insecure().next(ManagedUserVM.PASSWORD_MIN_LENGTH - 1);
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(
|
||||
post("/api/account/change-password")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(om.writeValueAsBytes(new PasswordChangeDTO(currentPassword, newPassword)))
|
||||
)
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
User updatedUser = userRepository.findOneByLogin("change-password-too-small").orElse(null);
|
||||
assertThat(updatedUser.getPassword()).isEqualTo(user.getPassword());
|
||||
|
||||
userService.deleteUser("change-password-too-small");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@WithMockUser("change-password-too-long")
|
||||
void testChangePasswordTooLong() throws Exception {
|
||||
User user = new User();
|
||||
String currentPassword = RandomStringUtils.insecure().nextAlphanumeric(60);
|
||||
user.setPassword(passwordEncoder.encode(currentPassword));
|
||||
user.setLogin("change-password-too-long");
|
||||
user.setEmail("change-password-too-long@example.com");
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
String newPassword = RandomStringUtils.insecure().next(ManagedUserVM.PASSWORD_MAX_LENGTH + 1);
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(
|
||||
post("/api/account/change-password")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(om.writeValueAsBytes(new PasswordChangeDTO(currentPassword, newPassword)))
|
||||
)
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
User updatedUser = userRepository.findOneByLogin("change-password-too-long").orElse(null);
|
||||
assertThat(updatedUser.getPassword()).isEqualTo(user.getPassword());
|
||||
|
||||
userService.deleteUser("change-password-too-long");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
@WithMockUser("change-password-empty")
|
||||
void testChangePasswordEmpty() throws Exception {
|
||||
User user = new User();
|
||||
String currentPassword = RandomStringUtils.insecure().nextAlphanumeric(60);
|
||||
user.setPassword(passwordEncoder.encode(currentPassword));
|
||||
user.setLogin("change-password-empty");
|
||||
user.setEmail("change-password-empty@example.com");
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(
|
||||
post("/api/account/change-password")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(om.writeValueAsBytes(new PasswordChangeDTO(currentPassword, "")))
|
||||
)
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
User updatedUser = userRepository.findOneByLogin("change-password-empty").orElse(null);
|
||||
assertThat(updatedUser.getPassword()).isEqualTo(user.getPassword());
|
||||
|
||||
userService.deleteUser("change-password-empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testRequestPasswordReset() throws Exception {
|
||||
User user = new User();
|
||||
user.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
user.setActivated(true);
|
||||
user.setLogin("password-reset");
|
||||
user.setEmail("password-reset@example.com");
|
||||
user.setLangKey("en");
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/account/reset-password/init").content("password-reset@example.com"))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
userService.deleteUser("password-reset");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testRequestPasswordResetUpperCaseEmail() throws Exception {
|
||||
User user = new User();
|
||||
user.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
user.setActivated(true);
|
||||
user.setLogin("password-reset-upper-case");
|
||||
user.setEmail("password-reset-upper-case@example.com");
|
||||
user.setLangKey("en");
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/account/reset-password/init").content("password-reset-upper-case@EXAMPLE.COM"))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
userService.deleteUser("password-reset-upper-case");
|
||||
}
|
||||
|
||||
@Test
|
||||
void testRequestPasswordResetWrongEmail() throws Exception {
|
||||
restAccountMockMvc
|
||||
.perform(post("/api/account/reset-password/init").content("password-reset-wrong-email@example.com"))
|
||||
.andExpect(status().isOk());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testFinishPasswordReset() throws Exception {
|
||||
User user = new User();
|
||||
user.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
user.setLogin("finish-password-reset");
|
||||
user.setEmail("finish-password-reset@example.com");
|
||||
user.setResetDate(Instant.now().plusSeconds(60));
|
||||
user.setResetKey("reset key");
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
KeyAndPasswordVM keyAndPassword = new KeyAndPasswordVM();
|
||||
keyAndPassword.setKey(user.getResetKey());
|
||||
keyAndPassword.setNewPassword("new password");
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(
|
||||
post("/api/account/reset-password/finish")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(om.writeValueAsBytes(keyAndPassword))
|
||||
)
|
||||
.andExpect(status().isOk());
|
||||
|
||||
User updatedUser = userRepository.findOneByLogin(user.getLogin()).orElse(null);
|
||||
assertThat(passwordEncoder.matches(keyAndPassword.getNewPassword(), updatedUser.getPassword())).isTrue();
|
||||
|
||||
userService.deleteUser("finish-password-reset");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testFinishPasswordResetTooSmall() throws Exception {
|
||||
User user = new User();
|
||||
user.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
user.setLogin("finish-password-reset-too-small");
|
||||
user.setEmail("finish-password-reset-too-small@example.com");
|
||||
user.setResetDate(Instant.now().plusSeconds(60));
|
||||
user.setResetKey("reset key too small");
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
KeyAndPasswordVM keyAndPassword = new KeyAndPasswordVM();
|
||||
keyAndPassword.setKey(user.getResetKey());
|
||||
keyAndPassword.setNewPassword("foo");
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(
|
||||
post("/api/account/reset-password/finish")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(om.writeValueAsBytes(keyAndPassword))
|
||||
)
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
User updatedUser = userRepository.findOneByLogin(user.getLogin()).orElse(null);
|
||||
assertThat(passwordEncoder.matches(keyAndPassword.getNewPassword(), updatedUser.getPassword())).isFalse();
|
||||
|
||||
userService.deleteUser("finish-password-reset-too-small");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testFinishPasswordResetWrongKey() throws Exception {
|
||||
KeyAndPasswordVM keyAndPassword = new KeyAndPasswordVM();
|
||||
keyAndPassword.setKey("wrong reset key");
|
||||
keyAndPassword.setNewPassword("new password");
|
||||
|
||||
restAccountMockMvc
|
||||
.perform(
|
||||
post("/api/account/reset-password/finish")
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content(om.writeValueAsBytes(keyAndPassword))
|
||||
)
|
||||
.andExpect(status().isInternalServerError());
|
||||
}
|
||||
}
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
package com.sisvietnamvn.web.web.rest;
|
||||
|
||||
import static org.hamcrest.Matchers.emptyString;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.header;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.sisvietnamvn.web.IntegrationTest;
|
||||
import com.sisvietnamvn.web.domain.User;
|
||||
import com.sisvietnamvn.web.repository.UserRepository;
|
||||
import com.sisvietnamvn.web.web.rest.vm.LoginVM;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link AuthenticateController} REST controller.
|
||||
*/
|
||||
@AutoConfigureMockMvc
|
||||
@IntegrationTest
|
||||
class AuthenticateControllerIT {
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper om;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testAuthorize() throws Exception {
|
||||
User user = new User();
|
||||
user.setLogin("user-jwt-controller");
|
||||
user.setEmail("user-jwt-controller@example.com");
|
||||
user.setActivated(true);
|
||||
user.setPassword(passwordEncoder.encode("test"));
|
||||
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
LoginVM login = new LoginVM();
|
||||
login.setUsername("user-jwt-controller");
|
||||
login.setPassword("test");
|
||||
mockMvc
|
||||
.perform(post("/api/authenticate").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(login)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id_token").isString())
|
||||
.andExpect(jsonPath("$.id_token").isNotEmpty())
|
||||
.andExpect(header().string("Authorization", not(nullValue())))
|
||||
.andExpect(header().string("Authorization", not(is(emptyString()))));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void testAuthorizeWithRememberMe() throws Exception {
|
||||
User user = new User();
|
||||
user.setLogin("user-jwt-controller-remember-me");
|
||||
user.setEmail("user-jwt-controller-remember-me@example.com");
|
||||
user.setActivated(true);
|
||||
user.setPassword(passwordEncoder.encode("test"));
|
||||
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
LoginVM login = new LoginVM();
|
||||
login.setUsername("user-jwt-controller-remember-me");
|
||||
login.setPassword("test");
|
||||
login.setRememberMe(true);
|
||||
mockMvc
|
||||
.perform(post("/api/authenticate").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(login)))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(jsonPath("$.id_token").isString())
|
||||
.andExpect(jsonPath("$.id_token").isNotEmpty())
|
||||
.andExpect(header().string("Authorization", not(nullValue())))
|
||||
.andExpect(header().string("Authorization", not(is(emptyString()))));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAuthorizeFails() throws Exception {
|
||||
LoginVM login = new LoginVM();
|
||||
login.setUsername("wrong-user");
|
||||
login.setPassword("wrong password");
|
||||
mockMvc
|
||||
.perform(post("/api/authenticate").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(login)))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(jsonPath("$.id_token").doesNotExist())
|
||||
.andExpect(header().doesNotExist("Authorization"));
|
||||
}
|
||||
}
|
||||
+206
@@ -0,0 +1,206 @@
|
||||
package com.sisvietnamvn.web.web.rest;
|
||||
|
||||
import static com.sisvietnamvn.web.domain.AuthorityAsserts.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.sisvietnamvn.web.IntegrationTest;
|
||||
import com.sisvietnamvn.web.domain.Authority;
|
||||
import com.sisvietnamvn.web.repository.AuthorityRepository;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import java.util.UUID;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link AuthorityResource} REST controller.
|
||||
*/
|
||||
@IntegrationTest
|
||||
@AutoConfigureMockMvc
|
||||
@WithMockUser(authorities = { "ROLE_ADMIN" })
|
||||
class AuthorityResourceIT {
|
||||
|
||||
private static final String ENTITY_API_URL = "/api/authorities";
|
||||
private static final String ENTITY_API_URL_ID = ENTITY_API_URL + "/{name}";
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper om;
|
||||
|
||||
@Autowired
|
||||
private AuthorityRepository authorityRepository;
|
||||
|
||||
@Autowired
|
||||
private EntityManager em;
|
||||
|
||||
@Autowired
|
||||
private MockMvc restAuthorityMockMvc;
|
||||
|
||||
private Authority authority;
|
||||
|
||||
private Authority insertedAuthority;
|
||||
|
||||
/**
|
||||
* Create an entity for this test.
|
||||
*
|
||||
* This is a static method, as tests for other entities might also need it,
|
||||
* if they test an entity which requires the current entity.
|
||||
*/
|
||||
public static Authority createEntity() {
|
||||
return new Authority().name(UUID.randomUUID().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an updated entity for this test.
|
||||
*
|
||||
* This is a static method, as tests for other entities might also need it,
|
||||
* if they test an entity which requires the current entity.
|
||||
*/
|
||||
public static Authority createUpdatedEntity() {
|
||||
return new Authority().name(UUID.randomUUID().toString());
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void initTest() {
|
||||
authority = createEntity();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanup() {
|
||||
if (insertedAuthority != null) {
|
||||
authorityRepository.delete(insertedAuthority);
|
||||
insertedAuthority = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void createAuthority() throws Exception {
|
||||
long databaseSizeBeforeCreate = getRepositoryCount();
|
||||
// Create the Authority
|
||||
var returnedAuthority = om.readValue(
|
||||
restAuthorityMockMvc
|
||||
.perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(authority)))
|
||||
.andExpect(status().isCreated())
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getContentAsString(),
|
||||
Authority.class
|
||||
);
|
||||
|
||||
// Validate the Authority in the database
|
||||
assertIncrementedRepositoryCount(databaseSizeBeforeCreate);
|
||||
assertAuthorityUpdatableFieldsEquals(returnedAuthority, getPersistedAuthority(returnedAuthority));
|
||||
|
||||
insertedAuthority = returnedAuthority;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void createAuthorityWithExistingId() throws Exception {
|
||||
// Create the Authority with an existing ID
|
||||
insertedAuthority = authorityRepository.saveAndFlush(authority);
|
||||
|
||||
long databaseSizeBeforeCreate = getRepositoryCount();
|
||||
|
||||
// An entity with an existing ID cannot be created, so this API call must fail
|
||||
restAuthorityMockMvc
|
||||
.perform(post(ENTITY_API_URL).contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(authority)))
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
// Validate the Authority in the database
|
||||
assertSameRepositoryCount(databaseSizeBeforeCreate);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void getAllAuthorities() throws Exception {
|
||||
// Initialize the database
|
||||
authority.setName(UUID.randomUUID().toString());
|
||||
insertedAuthority = authorityRepository.saveAndFlush(authority);
|
||||
|
||||
// Get all the authorityList
|
||||
restAuthorityMockMvc
|
||||
.perform(get(ENTITY_API_URL + "?sort=name,desc"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.[*].name").value(hasItem(authority.getName())));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void getAuthority() throws Exception {
|
||||
// Initialize the database
|
||||
authority.setName(UUID.randomUUID().toString());
|
||||
insertedAuthority = authorityRepository.saveAndFlush(authority);
|
||||
|
||||
// Get the authority
|
||||
restAuthorityMockMvc
|
||||
.perform(get(ENTITY_API_URL_ID, authority.getName()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.name").value(authority.getName()));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void getNonExistingAuthority() throws Exception {
|
||||
// Get the authority
|
||||
restAuthorityMockMvc.perform(get(ENTITY_API_URL_ID, Long.MAX_VALUE)).andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void deleteAuthority() throws Exception {
|
||||
// Initialize the database
|
||||
authority.setName(UUID.randomUUID().toString());
|
||||
insertedAuthority = authorityRepository.saveAndFlush(authority);
|
||||
|
||||
long databaseSizeBeforeDelete = getRepositoryCount();
|
||||
|
||||
// Delete the authority
|
||||
restAuthorityMockMvc
|
||||
.perform(delete(ENTITY_API_URL_ID, authority.getName()).accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
// Validate the database contains one less item
|
||||
assertDecrementedRepositoryCount(databaseSizeBeforeDelete);
|
||||
}
|
||||
|
||||
protected long getRepositoryCount() {
|
||||
return authorityRepository.count();
|
||||
}
|
||||
|
||||
protected void assertIncrementedRepositoryCount(long countBefore) {
|
||||
assertThat(countBefore + 1).isEqualTo(getRepositoryCount());
|
||||
}
|
||||
|
||||
protected void assertDecrementedRepositoryCount(long countBefore) {
|
||||
assertThat(countBefore - 1).isEqualTo(getRepositoryCount());
|
||||
}
|
||||
|
||||
protected void assertSameRepositoryCount(long countBefore) {
|
||||
assertThat(countBefore).isEqualTo(getRepositoryCount());
|
||||
}
|
||||
|
||||
protected Authority getPersistedAuthority(Authority authority) {
|
||||
return authorityRepository.findById(authority.getName()).orElseThrow();
|
||||
}
|
||||
|
||||
protected void assertPersistedAuthorityToMatchAllProperties(Authority expectedAuthority) {
|
||||
assertAuthorityAllPropertiesEquals(expectedAuthority, getPersistedAuthority(expectedAuthority));
|
||||
}
|
||||
|
||||
protected void assertPersistedAuthorityToMatchUpdatableProperties(Authority expectedAuthority) {
|
||||
assertAuthorityAllUpdatablePropertiesEquals(expectedAuthority, getPersistedAuthority(expectedAuthority));
|
||||
}
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
package com.sisvietnamvn.web.web.rest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import com.sisvietnamvn.web.IntegrationTest;
|
||||
import com.sisvietnamvn.web.domain.User;
|
||||
import com.sisvietnamvn.web.repository.UserRepository;
|
||||
import com.sisvietnamvn.web.security.AuthoritiesConstants;
|
||||
import com.sisvietnamvn.web.service.UserService;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link PublicUserResource} REST controller.
|
||||
*/
|
||||
@AutoConfigureMockMvc
|
||||
@WithMockUser(authorities = AuthoritiesConstants.ADMIN)
|
||||
@IntegrationTest
|
||||
class PublicUserResourceIT {
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private CacheManager cacheManager;
|
||||
|
||||
@Autowired
|
||||
private MockMvc restUserMockMvc;
|
||||
|
||||
private User user;
|
||||
private Long numberOfUsers;
|
||||
|
||||
@BeforeEach
|
||||
void countUsers() {
|
||||
numberOfUsers = userRepository.count();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void initTest() {
|
||||
user = UserResourceIT.initTestUser();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanupAndCheck() {
|
||||
cacheManager
|
||||
.getCacheNames()
|
||||
.stream()
|
||||
.map(cacheName -> this.cacheManager.getCache(cacheName))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(Cache::clear);
|
||||
userService.deleteUser(user.getLogin());
|
||||
assertThat(userRepository.count()).isEqualTo(numberOfUsers);
|
||||
numberOfUsers = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void getAllPublicUsers() throws Exception {
|
||||
// Initialize the database
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
// Get all the users
|
||||
restUserMockMvc
|
||||
.perform(get("/api/users?sort=id,desc").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.[?(@.id == %d)].login".formatted(user.getId())).value(user.getLogin()))
|
||||
.andExpect(jsonPath("$.[?(@.id == %d)].keys()".formatted(user.getId())).value(Set.of("id", "login")))
|
||||
.andExpect(jsonPath("$.[*].email").doesNotHaveJsonPath())
|
||||
.andExpect(jsonPath("$.[*].imageUrl").doesNotHaveJsonPath())
|
||||
.andExpect(jsonPath("$.[*].langKey").doesNotHaveJsonPath());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void getAllUsersSortedByParameters() throws Exception {
|
||||
// Initialize the database
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
restUserMockMvc.perform(get("/api/users?sort=resetKey,desc").accept(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest());
|
||||
restUserMockMvc.perform(get("/api/users?sort=password,desc").accept(MediaType.APPLICATION_JSON)).andExpect(status().isBadRequest());
|
||||
restUserMockMvc
|
||||
.perform(get("/api/users?sort=resetKey,desc&sort=id,desc").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isBadRequest());
|
||||
restUserMockMvc.perform(get("/api/users?sort=id,desc").accept(MediaType.APPLICATION_JSON)).andExpect(status().isOk());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
package com.sisvietnamvn.web.web.rest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
import jakarta.persistence.EntityManager;
|
||||
import jakarta.persistence.TypedQuery;
|
||||
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||
import jakarta.persistence.criteria.CriteriaQuery;
|
||||
import jakarta.persistence.criteria.Root;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.TypeSafeDiagnosingMatcher;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.cglib.proxy.MethodInterceptor;
|
||||
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
|
||||
import org.springframework.format.support.DefaultFormattingConversionService;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
|
||||
/**
|
||||
* Utility class for testing REST controllers.
|
||||
*/
|
||||
public final class TestUtil {
|
||||
|
||||
/**
|
||||
* Create a byte array with a specific size filled with specified data.
|
||||
*
|
||||
* @param size the size of the byte array.
|
||||
* @param data the data to put in the byte array.
|
||||
* @return the JSON byte array.
|
||||
*/
|
||||
public static byte[] createByteArray(int size, String data) {
|
||||
byte[] byteArray = new byte[size];
|
||||
Arrays.fill(byteArray, Byte.parseByte(data, 2));
|
||||
return byteArray;
|
||||
}
|
||||
|
||||
/**
|
||||
* A matcher that tests that the examined string represents the same instant as the reference datetime.
|
||||
*/
|
||||
public static class ZonedDateTimeMatcher extends TypeSafeDiagnosingMatcher<String> {
|
||||
|
||||
private final ZonedDateTime date;
|
||||
|
||||
public ZonedDateTimeMatcher(ZonedDateTime date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(String item, Description mismatchDescription) {
|
||||
try {
|
||||
if (!date.isEqual(ZonedDateTime.parse(item))) {
|
||||
mismatchDescription.appendText("was ").appendValue(item);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} catch (DateTimeParseException e) {
|
||||
mismatchDescription.appendText("was ").appendValue(item).appendText(", which could not be parsed as a ZonedDateTime");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("a String representing the same Instant as ").appendValue(date);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a matcher that matches when the examined string represents the same instant as the reference datetime.
|
||||
*
|
||||
* @param date the reference datetime against which the examined string is checked.
|
||||
*/
|
||||
public static ZonedDateTimeMatcher sameInstant(ZonedDateTime date) {
|
||||
return new ZonedDateTimeMatcher(date);
|
||||
}
|
||||
|
||||
/**
|
||||
* A matcher that tests that the examined number represents the same value - it can be Long, Double, etc - as the reference BigDecimal.
|
||||
*/
|
||||
public static class NumberMatcher extends TypeSafeMatcher<Number> {
|
||||
|
||||
final BigDecimal value;
|
||||
|
||||
public NumberMatcher(BigDecimal value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText("a numeric value is ").appendValue(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(Number item) {
|
||||
BigDecimal bigDecimal = asDecimal(item);
|
||||
return bigDecimal != null && value.compareTo(bigDecimal) == 0;
|
||||
}
|
||||
|
||||
private static BigDecimal asDecimal(Number item) {
|
||||
return switch (item) {
|
||||
case null -> null;
|
||||
case BigDecimal bigDecimal -> bigDecimal;
|
||||
case Long l -> BigDecimal.valueOf(l);
|
||||
case Integer i -> BigDecimal.valueOf(i);
|
||||
case Double v -> BigDecimal.valueOf(v);
|
||||
case Float v -> BigDecimal.valueOf(v);
|
||||
default -> BigDecimal.valueOf(item.doubleValue());
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a matcher that matches when the examined number represents the same value as the reference BigDecimal.
|
||||
*
|
||||
* @param number the reference BigDecimal against which the examined number is checked.
|
||||
*/
|
||||
public static NumberMatcher sameNumber(BigDecimal number) {
|
||||
return new NumberMatcher(number);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the equals/hashcode contract on the domain object.
|
||||
*/
|
||||
public static <T> void equalsVerifier(Class<T> clazz) throws Exception {
|
||||
T domainObject1 = clazz.getConstructor().newInstance();
|
||||
assertThat(domainObject1.toString()).isNotNull();
|
||||
assertThat(domainObject1).isEqualTo(domainObject1);
|
||||
assertThat(domainObject1).hasSameHashCodeAs(domainObject1);
|
||||
// Test with an instance of another class
|
||||
Object testOtherObject = new Object();
|
||||
assertThat(domainObject1).isNotEqualTo(testOtherObject);
|
||||
assertThat(domainObject1).isNotEqualTo(null);
|
||||
// Test with an instance of the same class
|
||||
T domainObject2 = clazz.getConstructor().newInstance();
|
||||
assertThat(domainObject1).isNotEqualTo(domainObject2);
|
||||
// HashCodes are equals because the objects are not persisted yet
|
||||
assertThat(domainObject1).hasSameHashCodeAs(domainObject2);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link FormattingConversionService} which use ISO date format, instead of the localized one.
|
||||
* @return the {@link FormattingConversionService}.
|
||||
*/
|
||||
public static FormattingConversionService createFormattingConversionService() {
|
||||
DefaultFormattingConversionService dfcs = new DefaultFormattingConversionService();
|
||||
var registrar = new DateTimeFormatterRegistrar();
|
||||
registrar.setUseIsoFormat(true);
|
||||
registrar.registerFormatters(dfcs);
|
||||
return dfcs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a query on the EntityManager finding all stored objects.
|
||||
* @param <T> The type of objects to be searched
|
||||
* @param em The instance of the EntityManager
|
||||
* @param clazz The class type to be searched
|
||||
* @return A list of all found objects
|
||||
*/
|
||||
public static <T> List<T> findAll(EntityManager em, Class<T> clazz) {
|
||||
CriteriaBuilder cb = em.getCriteriaBuilder();
|
||||
CriteriaQuery<T> cq = cb.createQuery(clazz);
|
||||
Root<T> rootEntry = cq.from(clazz);
|
||||
CriteriaQuery<T> all = cq.select(rootEntry);
|
||||
TypedQuery<T> allQuery = em.createQuery(all);
|
||||
return allQuery.getResultList();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public static <T> T createUpdateProxyForBean(T update, T original) {
|
||||
Enhancer e = new Enhancer();
|
||||
e.setSuperclass(original.getClass());
|
||||
e.setCallback(
|
||||
(MethodInterceptor) (obj, method, args, proxy) -> {
|
||||
Object val = update.getClass().getMethod(method.getName(), method.getParameterTypes()).invoke(update, args);
|
||||
if (val == null) {
|
||||
return original.getClass().getMethod(method.getName(), method.getParameterTypes()).invoke(original, args);
|
||||
}
|
||||
return val;
|
||||
}
|
||||
);
|
||||
return (T) e.create();
|
||||
}
|
||||
|
||||
private TestUtil() {}
|
||||
}
|
||||
@@ -0,0 +1,505 @@
|
||||
package com.sisvietnamvn.web.web.rest;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.hamcrest.Matchers.hasItem;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.sisvietnamvn.web.IntegrationTest;
|
||||
import com.sisvietnamvn.web.domain.User;
|
||||
import com.sisvietnamvn.web.repository.UserRepository;
|
||||
import com.sisvietnamvn.web.security.AuthoritiesConstants;
|
||||
import com.sisvietnamvn.web.service.UserService;
|
||||
import com.sisvietnamvn.web.service.dto.AdminUserDTO;
|
||||
import com.sisvietnamvn.web.service.mapper.UserMapper;
|
||||
import jakarta.persistence.EntityManager;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.CacheManager;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link UserResource} REST controller.
|
||||
*/
|
||||
@AutoConfigureMockMvc
|
||||
@WithMockUser(authorities = AuthoritiesConstants.ADMIN)
|
||||
@IntegrationTest
|
||||
class UserResourceIT {
|
||||
|
||||
private static final String DEFAULT_LOGIN = "johndoe";
|
||||
private static final String UPDATED_LOGIN = "jhipster";
|
||||
|
||||
private static final Long DEFAULT_ID = 1L;
|
||||
|
||||
private static final String DEFAULT_EMAIL = "johndoe@localhost";
|
||||
private static final String UPDATED_EMAIL = "jhipster@localhost";
|
||||
|
||||
private static final String DEFAULT_FIRSTNAME = "john";
|
||||
private static final String UPDATED_FIRSTNAME = "jhipsterFirstName";
|
||||
|
||||
private static final String DEFAULT_LASTNAME = "doe";
|
||||
private static final String UPDATED_LASTNAME = "jhipsterLastName";
|
||||
|
||||
private static final String DEFAULT_IMAGEURL = "http://placehold.it/50x50";
|
||||
private static final String UPDATED_IMAGEURL = "http://placehold.it/40x40";
|
||||
|
||||
private static final String DEFAULT_LANGKEY = "en";
|
||||
private static final String UPDATED_LANGKEY = "fr";
|
||||
|
||||
@Autowired
|
||||
private ObjectMapper om;
|
||||
|
||||
@Autowired
|
||||
private UserRepository userRepository;
|
||||
|
||||
@Autowired
|
||||
private UserService userService;
|
||||
|
||||
@Autowired
|
||||
private UserMapper userMapper;
|
||||
|
||||
@Autowired
|
||||
private EntityManager em;
|
||||
|
||||
@Autowired
|
||||
private CacheManager cacheManager;
|
||||
|
||||
@Autowired
|
||||
private MockMvc restUserMockMvc;
|
||||
|
||||
private User user;
|
||||
|
||||
private Long numberOfUsers;
|
||||
|
||||
@BeforeEach
|
||||
void countUsers() {
|
||||
numberOfUsers = userRepository.count();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a User.
|
||||
*
|
||||
* This is a static method, as tests for other entities might also need it,
|
||||
* if they test an entity which has a required relationship to the User entity.
|
||||
*/
|
||||
public static User createEntity() {
|
||||
User persistUser = new User();
|
||||
persistUser.setLogin(DEFAULT_LOGIN + RandomStringUtils.insecure().nextAlphabetic(5));
|
||||
persistUser.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
persistUser.setActivated(true);
|
||||
persistUser.setEmail(RandomStringUtils.insecure().nextAlphabetic(5) + DEFAULT_EMAIL);
|
||||
persistUser.setFirstName(DEFAULT_FIRSTNAME);
|
||||
persistUser.setLastName(DEFAULT_LASTNAME);
|
||||
persistUser.setImageUrl(DEFAULT_IMAGEURL);
|
||||
persistUser.setLangKey(DEFAULT_LANGKEY);
|
||||
return persistUser;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setups the database with one user.
|
||||
*/
|
||||
public static User initTestUser() {
|
||||
User persistUser = createEntity();
|
||||
persistUser.setLogin(DEFAULT_LOGIN);
|
||||
persistUser.setEmail(DEFAULT_EMAIL);
|
||||
return persistUser;
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
void initTest() {
|
||||
user = initTestUser();
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void cleanupAndCheck() {
|
||||
userService.deleteUser(DEFAULT_LOGIN);
|
||||
userService.deleteUser(UPDATED_LOGIN);
|
||||
userService.deleteUser(user.getLogin());
|
||||
userService.deleteUser("anotherlogin");
|
||||
assertThat(userRepository.count()).isEqualTo(numberOfUsers);
|
||||
numberOfUsers = null;
|
||||
cacheManager
|
||||
.getCacheNames()
|
||||
.stream()
|
||||
.map(cacheName -> this.cacheManager.getCache(cacheName))
|
||||
.filter(Objects::nonNull)
|
||||
.forEach(Cache::invalidate);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void createUser() throws Exception {
|
||||
// Create the User
|
||||
AdminUserDTO userDTO = new AdminUserDTO();
|
||||
userDTO.setLogin(DEFAULT_LOGIN);
|
||||
userDTO.setFirstName(DEFAULT_FIRSTNAME);
|
||||
userDTO.setLastName(DEFAULT_LASTNAME);
|
||||
userDTO.setEmail(DEFAULT_EMAIL);
|
||||
userDTO.setActivated(true);
|
||||
userDTO.setImageUrl(DEFAULT_IMAGEURL);
|
||||
userDTO.setLangKey(DEFAULT_LANGKEY);
|
||||
userDTO.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
|
||||
var returnedUserDTO = om.readValue(
|
||||
restUserMockMvc
|
||||
.perform(post("/api/admin/users").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userDTO)))
|
||||
.andExpect(status().isCreated())
|
||||
.andReturn()
|
||||
.getResponse()
|
||||
.getContentAsString(),
|
||||
AdminUserDTO.class
|
||||
);
|
||||
|
||||
User convertedUser = userMapper.userDTOToUser(returnedUserDTO);
|
||||
// Validate the returned User
|
||||
assertThat(convertedUser.getLogin()).isEqualTo(DEFAULT_LOGIN);
|
||||
assertThat(convertedUser.getFirstName()).isEqualTo(DEFAULT_FIRSTNAME);
|
||||
assertThat(convertedUser.getLastName()).isEqualTo(DEFAULT_LASTNAME);
|
||||
assertThat(convertedUser.getEmail()).isEqualTo(DEFAULT_EMAIL);
|
||||
assertThat(convertedUser.getImageUrl()).isEqualTo(DEFAULT_IMAGEURL);
|
||||
assertThat(convertedUser.getLangKey()).isEqualTo(DEFAULT_LANGKEY);
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void createUserWithExistingId() throws Exception {
|
||||
int databaseSizeBeforeCreate = userRepository.findAll().size();
|
||||
|
||||
AdminUserDTO userDTO = new AdminUserDTO();
|
||||
userDTO.setId(DEFAULT_ID);
|
||||
userDTO.setLogin(DEFAULT_LOGIN);
|
||||
userDTO.setFirstName(DEFAULT_FIRSTNAME);
|
||||
userDTO.setLastName(DEFAULT_LASTNAME);
|
||||
userDTO.setEmail(DEFAULT_EMAIL);
|
||||
userDTO.setActivated(true);
|
||||
userDTO.setImageUrl(DEFAULT_IMAGEURL);
|
||||
userDTO.setLangKey(DEFAULT_LANGKEY);
|
||||
userDTO.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
|
||||
// An entity with an existing ID cannot be created, so this API call must fail
|
||||
restUserMockMvc
|
||||
.perform(post("/api/admin/users").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userDTO)))
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
// Validate the User in the database
|
||||
assertPersistedUsers(users -> assertThat(users).hasSize(databaseSizeBeforeCreate));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void createUserWithExistingLogin() throws Exception {
|
||||
// Initialize the database
|
||||
userRepository.saveAndFlush(user);
|
||||
int databaseSizeBeforeCreate = userRepository.findAll().size();
|
||||
|
||||
AdminUserDTO userDTO = new AdminUserDTO();
|
||||
userDTO.setLogin(DEFAULT_LOGIN); // this login should already be used
|
||||
userDTO.setFirstName(DEFAULT_FIRSTNAME);
|
||||
userDTO.setLastName(DEFAULT_LASTNAME);
|
||||
userDTO.setEmail("anothermail@localhost");
|
||||
userDTO.setActivated(true);
|
||||
userDTO.setImageUrl(DEFAULT_IMAGEURL);
|
||||
userDTO.setLangKey(DEFAULT_LANGKEY);
|
||||
userDTO.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
|
||||
// Create the User
|
||||
restUserMockMvc
|
||||
.perform(post("/api/admin/users").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userDTO)))
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
// Validate the User in the database
|
||||
assertPersistedUsers(users -> assertThat(users).hasSize(databaseSizeBeforeCreate));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void createUserWithExistingEmail() throws Exception {
|
||||
// Initialize the database
|
||||
userRepository.saveAndFlush(user);
|
||||
int databaseSizeBeforeCreate = userRepository.findAll().size();
|
||||
|
||||
AdminUserDTO userDTO = new AdminUserDTO();
|
||||
userDTO.setLogin("anotherlogin");
|
||||
userDTO.setFirstName(DEFAULT_FIRSTNAME);
|
||||
userDTO.setLastName(DEFAULT_LASTNAME);
|
||||
userDTO.setEmail(DEFAULT_EMAIL); // this email should already be used
|
||||
userDTO.setActivated(true);
|
||||
userDTO.setImageUrl(DEFAULT_IMAGEURL);
|
||||
userDTO.setLangKey(DEFAULT_LANGKEY);
|
||||
userDTO.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
|
||||
// Create the User
|
||||
restUserMockMvc
|
||||
.perform(post("/api/admin/users").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userDTO)))
|
||||
.andExpect(status().isBadRequest());
|
||||
|
||||
// Validate the User in the database
|
||||
assertPersistedUsers(users -> assertThat(users).hasSize(databaseSizeBeforeCreate));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void getAllUsers() throws Exception {
|
||||
// Initialize the database
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
// Get all the users
|
||||
restUserMockMvc
|
||||
.perform(get("/api/admin/users?sort=id,desc").accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.[*].login").value(hasItem(DEFAULT_LOGIN)))
|
||||
.andExpect(jsonPath("$.[*].firstName").value(hasItem(DEFAULT_FIRSTNAME)))
|
||||
.andExpect(jsonPath("$.[*].lastName").value(hasItem(DEFAULT_LASTNAME)))
|
||||
.andExpect(jsonPath("$.[*].email").value(hasItem(DEFAULT_EMAIL)))
|
||||
.andExpect(jsonPath("$.[*].imageUrl").value(hasItem(DEFAULT_IMAGEURL)))
|
||||
.andExpect(jsonPath("$.[*].langKey").value(hasItem(DEFAULT_LANGKEY)));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void getUser() throws Exception {
|
||||
// Initialize the database
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
assertThat(cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE).get(user.getLogin(), User.class)).isNull();
|
||||
|
||||
// Get the user
|
||||
restUserMockMvc
|
||||
.perform(get("/api/admin/users/{login}", user.getLogin()))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE))
|
||||
.andExpect(jsonPath("$.login").value(user.getLogin()))
|
||||
.andExpect(jsonPath("$.firstName").value(DEFAULT_FIRSTNAME))
|
||||
.andExpect(jsonPath("$.lastName").value(DEFAULT_LASTNAME))
|
||||
.andExpect(jsonPath("$.email").value(DEFAULT_EMAIL))
|
||||
.andExpect(jsonPath("$.imageUrl").value(DEFAULT_IMAGEURL))
|
||||
.andExpect(jsonPath("$.langKey").value(DEFAULT_LANGKEY));
|
||||
|
||||
assertThat(cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE).get(user.getLogin(), User.class)).isNotNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void getNonExistingUser() throws Exception {
|
||||
restUserMockMvc.perform(get("/api/admin/users/unknown")).andExpect(status().isNotFound());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void updateUser() throws Exception {
|
||||
// Initialize the database
|
||||
userRepository.saveAndFlush(user);
|
||||
int databaseSizeBeforeUpdate = userRepository.findAll().size();
|
||||
|
||||
// Update the user
|
||||
User updatedUser = userRepository.findById(user.getId()).orElseThrow();
|
||||
|
||||
AdminUserDTO userDTO = new AdminUserDTO();
|
||||
userDTO.setId(updatedUser.getId());
|
||||
userDTO.setLogin(updatedUser.getLogin());
|
||||
userDTO.setFirstName(UPDATED_FIRSTNAME);
|
||||
userDTO.setLastName(UPDATED_LASTNAME);
|
||||
userDTO.setEmail(UPDATED_EMAIL);
|
||||
userDTO.setActivated(updatedUser.isActivated());
|
||||
userDTO.setImageUrl(UPDATED_IMAGEURL);
|
||||
userDTO.setLangKey(UPDATED_LANGKEY);
|
||||
userDTO.setCreatedBy(updatedUser.getCreatedBy());
|
||||
userDTO.setCreatedDate(updatedUser.getCreatedDate());
|
||||
userDTO.setLastModifiedBy(updatedUser.getLastModifiedBy());
|
||||
userDTO.setLastModifiedDate(updatedUser.getLastModifiedDate());
|
||||
userDTO.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
|
||||
restUserMockMvc
|
||||
.perform(put("/api/admin/users").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userDTO)))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// Validate the User in the database
|
||||
assertPersistedUsers(users -> {
|
||||
assertThat(users).hasSize(databaseSizeBeforeUpdate);
|
||||
User testUser = users
|
||||
.stream()
|
||||
.filter(usr -> usr.getId().equals(updatedUser.getId()))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
assertThat(testUser.getFirstName()).isEqualTo(UPDATED_FIRSTNAME);
|
||||
assertThat(testUser.getLastName()).isEqualTo(UPDATED_LASTNAME);
|
||||
assertThat(testUser.getEmail()).isEqualTo(UPDATED_EMAIL);
|
||||
assertThat(testUser.getImageUrl()).isEqualTo(UPDATED_IMAGEURL);
|
||||
assertThat(testUser.getLangKey()).isEqualTo(UPDATED_LANGKEY);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void updateUserLogin() throws Exception {
|
||||
// Initialize the database
|
||||
userRepository.saveAndFlush(user);
|
||||
int databaseSizeBeforeUpdate = userRepository.findAll().size();
|
||||
|
||||
// Update the user
|
||||
User updatedUser = userRepository.findById(user.getId()).orElseThrow();
|
||||
|
||||
AdminUserDTO userDTO = new AdminUserDTO();
|
||||
userDTO.setId(updatedUser.getId());
|
||||
userDTO.setLogin(UPDATED_LOGIN);
|
||||
userDTO.setFirstName(UPDATED_FIRSTNAME);
|
||||
userDTO.setLastName(UPDATED_LASTNAME);
|
||||
userDTO.setEmail(UPDATED_EMAIL);
|
||||
userDTO.setActivated(updatedUser.isActivated());
|
||||
userDTO.setImageUrl(UPDATED_IMAGEURL);
|
||||
userDTO.setLangKey(UPDATED_LANGKEY);
|
||||
userDTO.setCreatedBy(updatedUser.getCreatedBy());
|
||||
userDTO.setCreatedDate(updatedUser.getCreatedDate());
|
||||
userDTO.setLastModifiedBy(updatedUser.getLastModifiedBy());
|
||||
userDTO.setLastModifiedDate(updatedUser.getLastModifiedDate());
|
||||
userDTO.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
|
||||
restUserMockMvc
|
||||
.perform(put("/api/admin/users").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userDTO)))
|
||||
.andExpect(status().isOk());
|
||||
|
||||
// Validate the User in the database
|
||||
assertPersistedUsers(users -> {
|
||||
assertThat(users).hasSize(databaseSizeBeforeUpdate);
|
||||
User testUser = users
|
||||
.stream()
|
||||
.filter(usr -> usr.getId().equals(updatedUser.getId()))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
assertThat(testUser.getLogin()).isEqualTo(UPDATED_LOGIN);
|
||||
assertThat(testUser.getFirstName()).isEqualTo(UPDATED_FIRSTNAME);
|
||||
assertThat(testUser.getLastName()).isEqualTo(UPDATED_LASTNAME);
|
||||
assertThat(testUser.getEmail()).isEqualTo(UPDATED_EMAIL);
|
||||
assertThat(testUser.getImageUrl()).isEqualTo(UPDATED_IMAGEURL);
|
||||
assertThat(testUser.getLangKey()).isEqualTo(UPDATED_LANGKEY);
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void updateUserExistingEmail() throws Exception {
|
||||
// Initialize the database with 2 users
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
User anotherUser = new User();
|
||||
anotherUser.setLogin("jhipster");
|
||||
anotherUser.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
anotherUser.setActivated(true);
|
||||
anotherUser.setEmail("jhipster@localhost");
|
||||
anotherUser.setFirstName("java");
|
||||
anotherUser.setLastName("hipster");
|
||||
anotherUser.setImageUrl("");
|
||||
anotherUser.setLangKey("en");
|
||||
userRepository.saveAndFlush(anotherUser);
|
||||
|
||||
// Update the user
|
||||
User updatedUser = userRepository.findById(user.getId()).orElseThrow();
|
||||
|
||||
AdminUserDTO userDTO = new AdminUserDTO();
|
||||
userDTO.setId(updatedUser.getId());
|
||||
userDTO.setLogin(updatedUser.getLogin());
|
||||
userDTO.setFirstName(updatedUser.getFirstName());
|
||||
userDTO.setLastName(updatedUser.getLastName());
|
||||
userDTO.setEmail("jhipster@localhost"); // this email should already be used by anotherUser
|
||||
userDTO.setActivated(updatedUser.isActivated());
|
||||
userDTO.setImageUrl(updatedUser.getImageUrl());
|
||||
userDTO.setLangKey(updatedUser.getLangKey());
|
||||
userDTO.setCreatedBy(updatedUser.getCreatedBy());
|
||||
userDTO.setCreatedDate(updatedUser.getCreatedDate());
|
||||
userDTO.setLastModifiedBy(updatedUser.getLastModifiedBy());
|
||||
userDTO.setLastModifiedDate(updatedUser.getLastModifiedDate());
|
||||
userDTO.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
|
||||
restUserMockMvc
|
||||
.perform(put("/api/admin/users").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userDTO)))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void updateUserExistingLogin() throws Exception {
|
||||
// Initialize the database
|
||||
userRepository.saveAndFlush(user);
|
||||
|
||||
User anotherUser = new User();
|
||||
anotherUser.setLogin("jhipster");
|
||||
anotherUser.setPassword(RandomStringUtils.insecure().nextAlphanumeric(60));
|
||||
anotherUser.setActivated(true);
|
||||
anotherUser.setEmail("jhipster@localhost");
|
||||
anotherUser.setFirstName("java");
|
||||
anotherUser.setLastName("hipster");
|
||||
anotherUser.setImageUrl("");
|
||||
anotherUser.setLangKey("en");
|
||||
userRepository.saveAndFlush(anotherUser);
|
||||
|
||||
// Update the user
|
||||
User updatedUser = userRepository.findById(user.getId()).orElseThrow();
|
||||
|
||||
AdminUserDTO userDTO = new AdminUserDTO();
|
||||
userDTO.setId(updatedUser.getId());
|
||||
userDTO.setLogin("jhipster"); // this login should already be used by anotherUser
|
||||
userDTO.setFirstName(updatedUser.getFirstName());
|
||||
userDTO.setLastName(updatedUser.getLastName());
|
||||
userDTO.setEmail(updatedUser.getEmail());
|
||||
userDTO.setActivated(updatedUser.isActivated());
|
||||
userDTO.setImageUrl(updatedUser.getImageUrl());
|
||||
userDTO.setLangKey(updatedUser.getLangKey());
|
||||
userDTO.setCreatedBy(updatedUser.getCreatedBy());
|
||||
userDTO.setCreatedDate(updatedUser.getCreatedDate());
|
||||
userDTO.setLastModifiedBy(updatedUser.getLastModifiedBy());
|
||||
userDTO.setLastModifiedDate(updatedUser.getLastModifiedDate());
|
||||
userDTO.setAuthorities(Set.of(AuthoritiesConstants.USER));
|
||||
|
||||
restUserMockMvc
|
||||
.perform(put("/api/admin/users").contentType(MediaType.APPLICATION_JSON).content(om.writeValueAsBytes(userDTO)))
|
||||
.andExpect(status().isBadRequest());
|
||||
}
|
||||
|
||||
@Test
|
||||
@Transactional
|
||||
void deleteUser() throws Exception {
|
||||
// Initialize the database
|
||||
userRepository.saveAndFlush(user);
|
||||
int databaseSizeBeforeDelete = userRepository.findAll().size();
|
||||
|
||||
// Delete the user
|
||||
restUserMockMvc
|
||||
.perform(delete("/api/admin/users/{login}", user.getLogin()).accept(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isNoContent());
|
||||
|
||||
assertThat(cacheManager.getCache(UserRepository.USERS_BY_LOGIN_CACHE).get(user.getLogin(), User.class)).isNull();
|
||||
|
||||
// Validate the database is empty
|
||||
assertPersistedUsers(users -> assertThat(users).hasSize(databaseSizeBeforeDelete - 1));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUserEquals() throws Exception {
|
||||
TestUtil.equalsVerifier(User.class);
|
||||
User user1 = new User();
|
||||
user1.setId(DEFAULT_ID);
|
||||
User user2 = new User();
|
||||
user2.setId(user1.getId());
|
||||
assertThat(user1).isEqualTo(user2);
|
||||
user2.setId(2L);
|
||||
assertThat(user1).isNotEqualTo(user2);
|
||||
user1.setId(null);
|
||||
assertThat(user1).isNotEqualTo(user2);
|
||||
}
|
||||
|
||||
private void assertPersistedUsers(Consumer<List<User>> userAssertion) {
|
||||
userAssertion.accept(userRepository.findAll());
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.sisvietnamvn.web.web.rest;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.test.context.support.WithSecurityContext;
|
||||
import org.springframework.security.test.context.support.WithSecurityContextFactory;
|
||||
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@WithSecurityContext(factory = WithUnauthenticatedMockUser.Factory.class)
|
||||
public @interface WithUnauthenticatedMockUser {
|
||||
class Factory implements WithSecurityContextFactory<WithUnauthenticatedMockUser> {
|
||||
|
||||
@Override
|
||||
public SecurityContext createSecurityContext(WithUnauthenticatedMockUser annotation) {
|
||||
return SecurityContextHolder.createEmptyContext();
|
||||
}
|
||||
}
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
package com.sisvietnamvn.web.web.rest.errors;
|
||||
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
import com.sisvietnamvn.web.IntegrationTest;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.webmvc.test.autoconfigure.AutoConfigureMockMvc;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.security.test.context.support.WithMockUser;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
|
||||
/**
|
||||
* Integration tests {@link ExceptionTranslator} controller advice.
|
||||
*/
|
||||
@WithMockUser
|
||||
@AutoConfigureMockMvc
|
||||
@IntegrationTest
|
||||
class ExceptionTranslatorIT {
|
||||
|
||||
@Autowired
|
||||
private MockMvc mockMvc;
|
||||
|
||||
@Test
|
||||
void testConcurrencyFailure() throws Exception {
|
||||
mockMvc
|
||||
.perform(get("/api/exception-translator-test/concurrency-failure"))
|
||||
.andExpect(status().isConflict())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON))
|
||||
.andExpect(jsonPath("$.message").value(ErrorConstants.ERR_CONCURRENCY_FAILURE));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMethodArgumentNotValid() throws Exception {
|
||||
mockMvc
|
||||
.perform(post("/api/exception-translator-test/method-argument").content("{}").contentType(MediaType.APPLICATION_JSON))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON))
|
||||
.andExpect(jsonPath("$.message").value(ErrorConstants.ERR_VALIDATION))
|
||||
.andExpect(jsonPath("$.fieldErrors.[0].objectName").value("test"))
|
||||
.andExpect(jsonPath("$.fieldErrors.[0].field").value("test"))
|
||||
.andExpect(jsonPath("$.fieldErrors.[0].message").value("must not be null"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMissingServletRequestPartException() throws Exception {
|
||||
mockMvc
|
||||
.perform(get("/api/exception-translator-test/missing-servlet-request-part"))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON))
|
||||
.andExpect(jsonPath("$.message").value("error.http.400"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMissingServletRequestParameterException() throws Exception {
|
||||
mockMvc
|
||||
.perform(get("/api/exception-translator-test/missing-servlet-request-parameter"))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON))
|
||||
.andExpect(jsonPath("$.message").value("error.http.400"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testAccessDenied() throws Exception {
|
||||
mockMvc
|
||||
.perform(get("/api/exception-translator-test/access-denied"))
|
||||
.andExpect(status().isForbidden())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON))
|
||||
.andExpect(jsonPath("$.message").value("error.http.403"))
|
||||
.andExpect(jsonPath("$.detail").value("test access denied!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testUnauthorized() throws Exception {
|
||||
mockMvc
|
||||
.perform(get("/api/exception-translator-test/unauthorized"))
|
||||
.andExpect(status().isUnauthorized())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON))
|
||||
.andExpect(jsonPath("$.message").value("error.http.401"))
|
||||
.andExpect(jsonPath("$.path").value("/api/exception-translator-test/unauthorized"))
|
||||
.andExpect(jsonPath("$.detail").value("test authentication failed!"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMethodNotSupported() throws Exception {
|
||||
mockMvc
|
||||
.perform(post("/api/exception-translator-test/access-denied"))
|
||||
.andExpect(status().isMethodNotAllowed())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON))
|
||||
.andExpect(jsonPath("$.message").value("error.http.405"))
|
||||
.andExpect(jsonPath("$.detail").value("Request method 'POST' is not supported"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testExceptionWithResponseStatus() throws Exception {
|
||||
mockMvc
|
||||
.perform(get("/api/exception-translator-test/response-status"))
|
||||
.andExpect(status().isBadRequest())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON))
|
||||
.andExpect(jsonPath("$.message").value("error.http.400"))
|
||||
.andExpect(jsonPath("$.title").value("test response status"));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testInternalServerError() throws Exception {
|
||||
mockMvc
|
||||
.perform(get("/api/exception-translator-test/internal-server-error"))
|
||||
.andExpect(status().isInternalServerError())
|
||||
.andExpect(content().contentType(MediaType.APPLICATION_PROBLEM_JSON))
|
||||
.andExpect(jsonPath("$.message").value("error.http.500"))
|
||||
.andExpect(jsonPath("$.title").value("Internal Server Error"));
|
||||
}
|
||||
}
|
||||
+72
@@ -0,0 +1,72 @@
|
||||
package com.sisvietnamvn.web.web.rest.errors;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import org.springframework.dao.ConcurrencyFailureException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.authentication.BadCredentialsException;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/exception-translator-test")
|
||||
public class ExceptionTranslatorTestController {
|
||||
|
||||
@GetMapping("/concurrency-failure")
|
||||
public void concurrencyFailure() {
|
||||
throw new ConcurrencyFailureException("test concurrency failure");
|
||||
}
|
||||
|
||||
@PostMapping("/method-argument")
|
||||
public void methodArgument(@Valid @RequestBody TestDTO testDTO) {
|
||||
// empty method
|
||||
}
|
||||
|
||||
@GetMapping("/missing-servlet-request-part")
|
||||
public void missingServletRequestPartException(@RequestPart("part") String part) {
|
||||
// empty method
|
||||
}
|
||||
|
||||
@GetMapping("/missing-servlet-request-parameter")
|
||||
public void missingServletRequestParameterException(@RequestParam("param") String param) {
|
||||
// empty method
|
||||
}
|
||||
|
||||
@GetMapping("/access-denied")
|
||||
public void accessdenied() {
|
||||
throw new AccessDeniedException("test access denied!");
|
||||
}
|
||||
|
||||
@GetMapping("/unauthorized")
|
||||
public void unauthorized() {
|
||||
throw new BadCredentialsException("test authentication failed!");
|
||||
}
|
||||
|
||||
@GetMapping("/response-status")
|
||||
public void exceptionWithResponseStatus() {
|
||||
throw new TestResponseStatusException();
|
||||
}
|
||||
|
||||
@GetMapping("/internal-server-error")
|
||||
public void internalServerError() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
public static class TestDTO {
|
||||
|
||||
@NotNull
|
||||
private String test;
|
||||
|
||||
public String getTest() {
|
||||
return test;
|
||||
}
|
||||
|
||||
public void setTest(String test) {
|
||||
this.test = test;
|
||||
}
|
||||
}
|
||||
|
||||
@ResponseStatus(value = HttpStatus.BAD_REQUEST, reason = "test response status")
|
||||
@SuppressWarnings("serial")
|
||||
public static class TestResponseStatusException extends RuntimeException {}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
org.springframework.test.context.ContextCustomizerFactory = \
|
||||
com.sisvietnamvn.web.config.SqlTestContainersSpringContextCustomizerFactory
|
||||
@@ -0,0 +1,33 @@
|
||||
# ===================================================================
|
||||
# Spring Boot configuration.
|
||||
#
|
||||
# This configuration is used for unit/integration tests with testcontainers database containers.
|
||||
#
|
||||
# To activate this configuration launch integration tests with the 'testcontainers' profile
|
||||
#
|
||||
# More information on database containers: https://www.testcontainers.org/modules/databases/
|
||||
# ===================================================================
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
url: jdbc:h2:file:./build/h2db/testdb/sisvietnamvn;DB_CLOSE_DELAY=-1
|
||||
username: sisvietnamvn
|
||||
password:
|
||||
hikari:
|
||||
auto-commit: false
|
||||
jpa:
|
||||
open-in-view: false
|
||||
hibernate:
|
||||
ddl-auto: none
|
||||
properties:
|
||||
hibernate.id.new_generator_mappings: true
|
||||
hibernate.connection.provider_disables_autocommit: true
|
||||
hibernate.cache.use_second_level_cache: false
|
||||
hibernate.cache.use_query_cache: false
|
||||
hibernate.generate_statistics: false
|
||||
hibernate.hbm2ddl.auto: none #TODO: temp relief for integration tests, revisit required
|
||||
hibernate.type.preferred_instant_jdbc_type: TIMESTAMP
|
||||
hibernate.jdbc.time_zone: UTC
|
||||
hibernate.timezone.default_storage: NORMALIZE
|
||||
hibernate.query.fail_on_pagination_over_collection_fetch: true
|
||||
@@ -0,0 +1,35 @@
|
||||
# ===================================================================
|
||||
# Spring Boot configuration.
|
||||
#
|
||||
# This configuration is used for unit/integration tests with testcontainers database containers.
|
||||
#
|
||||
# To activate this configuration launch integration tests with the 'testcontainers' profile
|
||||
#
|
||||
# More information on database containers: https://www.testcontainers.org/modules/databases/
|
||||
#
|
||||
# You have to specify an Oracle image name in a classpath file named testcontainers.properties.
|
||||
# Follow the instructions at https://www.testcontainers.org/modules/databases/oraclexe/
|
||||
# ===================================================================
|
||||
|
||||
spring:
|
||||
datasource:
|
||||
type: com.zaxxer.hikari.HikariDataSource
|
||||
hikari:
|
||||
poolName: Hikari
|
||||
auto-commit: false
|
||||
maximum-pool-size: 1
|
||||
jpa:
|
||||
open-in-view: false
|
||||
hibernate:
|
||||
ddl-auto: none
|
||||
properties:
|
||||
hibernate.id.new_generator_mappings: true
|
||||
hibernate.connection.provider_disables_autocommit: true
|
||||
hibernate.cache.use_second_level_cache: false
|
||||
hibernate.cache.use_query_cache: false
|
||||
hibernate.generate_statistics: false
|
||||
hibernate.hbm2ddl.auto: none #TODO: temp relief for integration tests, revisit required
|
||||
hibernate.type.preferred_instant_jdbc_type: TIMESTAMP
|
||||
hibernate.jdbc.time_zone: UTC
|
||||
hibernate.timezone.default_storage: NORMALIZE
|
||||
hibernate.query.fail_on_pagination_over_collection_fetch: true
|
||||
@@ -0,0 +1,94 @@
|
||||
# ===================================================================
|
||||
# Spring Boot configuration.
|
||||
#
|
||||
# This configuration is used for unit/integration tests.
|
||||
#
|
||||
# More information on profiles: https://www.jhipster.tech/profiles/
|
||||
# More information on configuration properties: https://www.jhipster.tech/common-application-properties/
|
||||
# ===================================================================
|
||||
|
||||
# ===================================================================
|
||||
# Standard Spring Boot properties.
|
||||
# Full reference is available at:
|
||||
# https://docs.spring.io/spring-boot/appendix/application-properties/index.html
|
||||
# ===================================================================
|
||||
|
||||
spring:
|
||||
application:
|
||||
name: sisvietnamvn
|
||||
# Replace by 'prod, faker' to add the faker context and have sample data loaded in production
|
||||
liquibase:
|
||||
contexts: test
|
||||
jackson2:
|
||||
serialization:
|
||||
write-durations-as-timestamps: false
|
||||
mail:
|
||||
host: localhost
|
||||
main:
|
||||
allow-bean-definition-overriding: true
|
||||
messages:
|
||||
basename: i18n/messages
|
||||
security:
|
||||
oauth2:
|
||||
resourceserver:
|
||||
jwt:
|
||||
authority-prefix: ''
|
||||
authorities-claim-name: auth
|
||||
task:
|
||||
execution:
|
||||
thread-name-prefix: sisvietnamvn-task-
|
||||
pool:
|
||||
core-size: 1
|
||||
max-size: 50
|
||||
queue-capacity: 10000
|
||||
scheduling:
|
||||
thread-name-prefix: sisvietnamvn-scheduling-
|
||||
pool:
|
||||
size: 20
|
||||
thymeleaf:
|
||||
mode: HTML
|
||||
|
||||
server:
|
||||
port: 10344
|
||||
address: localhost
|
||||
|
||||
# ===================================================================
|
||||
# JHipster specific properties
|
||||
#
|
||||
# Full reference is available at: https://www.jhipster.tech/common-application-properties/
|
||||
# ===================================================================
|
||||
jhipster:
|
||||
mail:
|
||||
from: sisvietnamvn@localhost.com
|
||||
base-url: http://127.0.0.1:8080
|
||||
logging:
|
||||
# To test json console appender
|
||||
use-json-format: false
|
||||
logstash:
|
||||
enabled: false
|
||||
host: localhost
|
||||
port: 5000
|
||||
ring-buffer-size: 512
|
||||
security:
|
||||
authentication:
|
||||
jwt:
|
||||
# This token must be encoded using Base64 (you can type `echo 'secret-key'|base64` on your command line)
|
||||
base64-secret: ZWRjOTBhYjJiYzg5N2JhMTUyMTBiYzZhNzJjMWUwNmYzOTM3MjJmZGE3Zjc3NGE0ODhjMDZlYzRjNmFiODFhMDNkNmFjNmYwYzY4NmMwNGRkMDMwY2Q0NTllNDlhYzEyMjg0NmY2NzM5MWM1M2IxOTdkMDNhZTBhZDkzYWJjMWI=
|
||||
# Token is valid 24 hours
|
||||
token-validity-in-seconds: 86400
|
||||
token-validity-in-seconds-for-remember-me: 86400
|
||||
|
||||
# ===================================================================
|
||||
# Application specific properties
|
||||
# Add your own application properties here, see the ApplicationProperties class
|
||||
# to have type-safe configuration, like in the JHipsterProperties above
|
||||
#
|
||||
# More documentation is available at:
|
||||
# https://www.jhipster.tech/common-application-properties/
|
||||
# ===================================================================
|
||||
|
||||
# application:
|
||||
management:
|
||||
health:
|
||||
mail:
|
||||
enabled: false
|
||||
@@ -0,0 +1,4 @@
|
||||
email.test.title=test title
|
||||
# Value used for English locale unit test in MailServiceIT
|
||||
# as this file is loaded instead of real file
|
||||
email.activation.title=sisvietnamvn account activation
|
||||
@@ -0,0 +1,4 @@
|
||||
junit.jupiter.execution.timeout.default = 15 s
|
||||
junit.jupiter.execution.timeout.testable.method.default = 15 s
|
||||
junit.jupiter.execution.timeout.beforeall.method.default = 60 s
|
||||
junit.jupiter.testclass.order.default=com.sisvietnamvn.web.config.SpringBootTestClassOrderer
|
||||
@@ -0,0 +1,45 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE configuration>
|
||||
|
||||
<configuration scan="true">
|
||||
<include resource="org/springframework/boot/logging/logback/base.xml"/>
|
||||
|
||||
<logger name="com.sisvietnamvn.web" level="INFO"/>
|
||||
|
||||
<logger name="tech.jhipster" level="WARN"/>
|
||||
|
||||
<!-- https://www.testcontainers.org/supported_docker_environment/logging_config/ -->
|
||||
<logger name="org.testcontainers" level="INFO"/>
|
||||
<logger name="com.github.dockerjava" level="WARN"/>
|
||||
|
||||
<logger name="jakarta.activation" level="WARN"/>
|
||||
<logger name="jakarta.mail" level="WARN"/>
|
||||
<logger name="jakarta.xml.bind" level="WARN"/>
|
||||
<logger name="ch.qos.logback" level="WARN"/>
|
||||
<logger name="com.jayway.jsonpath" level="WARN"/>
|
||||
<logger name="com.ryantenney" level="WARN"/>
|
||||
<logger name="com.sun" level="WARN"/>
|
||||
<logger name="com.zaxxer" level="WARN"/>
|
||||
<logger name="org.ehcache" level="WARN"/>
|
||||
<logger name="org.apache" level="WARN"/>
|
||||
<logger name="org.apache.catalina.startup.DigesterFactory" level="OFF"/>
|
||||
<logger name="org.bson" level="WARN"/>
|
||||
<logger name="org.hibernate.validator" level="WARN"/>
|
||||
<logger name="org.hibernate" level="WARN"/>
|
||||
<logger name="org.hibernate.ejb.HibernatePersistence" level="OFF"/>
|
||||
<logger name="org.springframework" level="WARN"/>
|
||||
<logger name="org.springframework.web" level="WARN"/>
|
||||
<logger name="org.springframework.security" level="WARN"/>
|
||||
<logger name="org.springframework.cache" level="WARN"/>
|
||||
<logger name="org.thymeleaf" level="WARN"/>
|
||||
<logger name="org.xnio" level="WARN"/>
|
||||
<logger name="io.swagger.v3" level="INFO"/>
|
||||
<logger name="sun.rmi" level="WARN"/>
|
||||
<logger name="sun.rmi.transport" level="WARN"/>
|
||||
<logger name="com.tngtech.archunit.core.importer" level="ERROR"/>
|
||||
<logger name="org.hibernate.orm.incubating" level="ERROR"/>
|
||||
<logger name="liquibase" level="WARN"/>
|
||||
<logger name="LiquibaseSchemaResolver" level="INFO"/>
|
||||
<!-- jhipster-needle-logback-add-log - JHipster will add a new log with level -->
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" th:lang="${#locale.language}" lang="en">
|
||||
<head>
|
||||
<title th:text="#{email.activation.title}">JHipster activation</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
</head>
|
||||
<body>
|
||||
<p th:text="#{email.activation.greeting(${user.login})}">Dear</p>
|
||||
<p th:text="#{email.activation.text1}">Your JHipster account has been created, please click on the URL below to activate it:</p>
|
||||
<p>
|
||||
<a th:with="url=(@{|${baseUrl}/account/activate?key=${user.activationKey}|})" th:href="${url}" th:text="${url}">Activation link</a>
|
||||
</p>
|
||||
<p>
|
||||
<span th:text="#{email.activation.text2}">Regards, </span>
|
||||
<br />
|
||||
<em th:text="#{email.signature}">JHipster.</em>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,19 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" th:lang="${#locale.language}" lang="en">
|
||||
<head>
|
||||
<title th:text="#{email.activation.title}">JHipster creation</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
</head>
|
||||
<body>
|
||||
<p th:text="#{email.activation.greeting(${user.login})}">Dear</p>
|
||||
<p th:text="#{email.creation.text1}">Your JHipster account has been created, please click on the URL below to access it:</p>
|
||||
<p>
|
||||
<a th:with="url=(@{|${baseUrl}/account/reset/finish?key=${user.resetKey}|})" th:href="${url}" th:text="${url}">Login link</a>
|
||||
</p>
|
||||
<p>
|
||||
<span th:text="#{email.activation.text2}">Regards, </span>
|
||||
<br />
|
||||
<em th:text="#{email.signature}">JHipster.</em>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,21 @@
|
||||
<!doctype html>
|
||||
<html xmlns:th="http://www.thymeleaf.org" th:lang="${#locale.language}" lang="en">
|
||||
<head>
|
||||
<title th:text="#{email.reset.title}">JHipster password reset</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
</head>
|
||||
<body>
|
||||
<p th:text="#{email.reset.greeting(${user.login})}">Dear</p>
|
||||
<p th:text="#{email.reset.text1}">
|
||||
For your JHipster account a password reset was requested, please click on the URL below to reset it:
|
||||
</p>
|
||||
<p>
|
||||
<a th:with="url=(@{|${baseUrl}/account/reset/finish?key=${user.resetKey}|})" th:href="${url}" th:text="${url}">Login link</a>
|
||||
</p>
|
||||
<p>
|
||||
<span th:text="#{email.reset.text2}">Regards, </span>
|
||||
<br />
|
||||
<em th:text="#{email.signature}">JHipster.</em>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1 @@
|
||||
<html xmlns:th="http://www.thymeleaf.org" th:text="|#{email.test.title}, ${baseUrl}, ${user.login}|"></html>
|
||||
Reference in New Issue
Block a user