Add support for configure http basic.

This commit is contained in:
Paulo Gustavo Veiga 2024-02-10 13:53:44 -08:00
parent 6f528835bf
commit f8b8aea901
12 changed files with 49 additions and 47 deletions

View File

@ -7,7 +7,7 @@ import com.wisemapping.security.Utils;
import com.wisemapping.service.MindmapServiceImpl; import com.wisemapping.service.MindmapServiceImpl;
import com.wisemapping.util.VelocityEngineUtils; import com.wisemapping.util.VelocityEngineUtils;
import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletRequest;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.NotNull;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
@ -23,14 +23,15 @@ import java.util.Locale;
public class CommonConfig { public class CommonConfig {
@Bean @Bean
public LocaleResolver localeResolver() { public LocaleResolver localeResolver() {
final LocaleResolver localeResolver = new AcceptHeaderLocaleResolver() { return new AcceptHeaderLocaleResolver() {
@Override @Override
public Locale resolveLocale(@Nullable HttpServletRequest request) { public Locale resolveLocale(@NotNull HttpServletRequest request) {
final User user = Utils.getUser(); final User user = Utils.getUser();
Locale result; Locale result;
if (user != null && user.getLocale() != null) {
String locale = user.getLocale(); String locale = user.getLocale();
if (user != null && locale != null) {
final String locales[] = locale.split("_"); final String locales[] = locale.split("_");
Locale.Builder builder = new Locale.Builder().setLanguage(locales[0]); Locale.Builder builder = new Locale.Builder().setLanguage(locales[0]);
if (locales.length > 1) { if (locales.length > 1) {
builder.setVariant(locales[1]); builder.setVariant(locales[1]);
@ -42,7 +43,6 @@ public class CommonConfig {
return result; return result;
} }
}; };
return localeResolver;
} }
} }

View File

@ -5,6 +5,7 @@ import com.wisemapping.rest.MindmapController;
import jakarta.servlet.http.HttpServletResponse; import jakarta.servlet.http.HttpServletResponse;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Import;
@ -25,6 +26,9 @@ import static org.springframework.security.config.Customizer.withDefaults;
@EnableWebSecurity @EnableWebSecurity
public class RestAppConfig { public class RestAppConfig {
@Value("${app.api.http-basic-enabled:false}")
private boolean enableHttpBasic;
@Autowired @Autowired
private JwtAuthenticationFilter jwtAuthenticationFilter; private JwtAuthenticationFilter jwtAuthenticationFilter;
@ -35,7 +39,7 @@ public class RestAppConfig {
@Bean @Bean
SecurityFilterChain apiSecurityFilterChain(@NotNull final HttpSecurity http, @NotNull final MvcRequestMatcher.Builder mvc) throws Exception { SecurityFilterChain apiSecurityFilterChain(@NotNull final HttpSecurity http, @NotNull final MvcRequestMatcher.Builder mvc) throws Exception {
return http http
.securityMatcher("/**") .securityMatcher("/**")
.addFilterAfter(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class) .addFilterAfter(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeHttpRequests(auth -> auth .authorizeHttpRequests(auth -> auth
@ -54,8 +58,13 @@ public class RestAppConfig {
response.setStatus(HttpServletResponse.SC_OK); response.setStatus(HttpServletResponse.SC_OK);
})) }))
.csrf(AbstractHttpConfigurer::disable) .csrf(AbstractHttpConfigurer::disable)
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS));
.httpBasic(withDefaults())
.build(); // Http basic is mainly used by automation tests.
if (enableHttpBasic) {
http.httpBasic(withDefaults());
}
return http.build();
} }
} }

View File

@ -1,23 +0,0 @@
/*
* Copyright [2022] [wisemapping]
*
* Licensed under WiseMapping Public License, Version 1.0 (the "License").
* It is basically the Apache License, Version 2.0 (the "License") plus the
* "powered by wisemapping" text requirement on every single page;
* you may not use this file except in compliance with the License.
* You may obtain a copy of the license at
*
* http://www.wisemapping.org/license
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.wisemapping.filter;
public interface SupportedUserAgent{
String USER_AGENT_HEADER = "User-Agent";
}

View File

@ -225,7 +225,7 @@ public class MindmapController extends BaseController {
final String title = restMindmap.getTitle(); final String title = restMindmap.getTitle();
if (title != null && !title.equals(mindmap.getTitle())) { if (title != null && !title.equals(mindmap.getTitle())) {
if (mindmapService.getMindmapByTitle(title, user) != null) { if (mindmapService.getMindmapByTitle(title, user) != null) {
throw buildValidationException("title", "You already have a map with this title"); throw buildValidationException("You already have a map with this title");
} }
mindmap.setTitle(title); mindmap.setTitle(title);
} }
@ -273,7 +273,7 @@ public class MindmapController extends BaseController {
// Is there a map with the same name ? // Is there a map with the same name ?
if (mindmapService.getMindmapByTitle(title, user) != null) { if (mindmapService.getMindmapByTitle(title, user) != null) {
throw buildValidationException("title", "You already have a mindmap with this title"); throw buildValidationException("You already have a mindmap with this title");
} }
// Update map ... // Update map ...
@ -497,7 +497,7 @@ public class MindmapController extends BaseController {
// Update map status ... // Update map status ...
final boolean starred = Boolean.parseBoolean(value); final boolean starred = Boolean.parseBoolean(value);
final Optional<Collaboration> collaboration = mindmap.findCollaboration(user); final Optional<Collaboration> collaboration = mindmap.findCollaboration(user);
if (!collaboration.isPresent()) { if (collaboration.isEmpty()) {
throw new WiseMappingException("No enough permissions."); throw new WiseMappingException("No enough permissions.");
} }
collaboration.get().getCollaborationProperties().setStarred(starred); collaboration.get().getCollaborationProperties().setStarred(starred);
@ -512,7 +512,7 @@ public class MindmapController extends BaseController {
final User user = Utils.getUser(); final User user = Utils.getUser();
final Optional<Collaboration> collaboration = mindmap.findCollaboration(user); final Optional<Collaboration> collaboration = mindmap.findCollaboration(user);
if (!collaboration.isPresent()) { if (collaboration.isEmpty()) {
throw new WiseMappingException("No enough permissions."); throw new WiseMappingException("No enough permissions.");
} }
boolean result = collaboration.get().getCollaborationProperties().getStarred(); boolean result = collaboration.get().getCollaborationProperties().getStarred();
@ -659,9 +659,9 @@ public class MindmapController extends BaseController {
mindmapService.updateMindmap(mindMap, !minor); mindmapService.updateMindmap(mindMap, !minor);
} }
private ValidationException buildValidationException(@NotNull String fieldName, @NotNull String message) throws WiseMappingException { private ValidationException buildValidationException(@NotNull String message) throws WiseMappingException {
final BindingResult result = new BeanPropertyBindingResult(new RestMindmap(), ""); final BindingResult result = new BeanPropertyBindingResult(new RestMindmap(), "");
result.rejectValue(fieldName, "error.not-specified", null, message); result.rejectValue("title", "error.not-specified", null, message);
return new ValidationException(result); return new ValidationException(result);
} }

View File

@ -22,7 +22,6 @@ import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration; import org.hibernate.cfg.Configuration;
public class HibernateUtil { public class HibernateUtil {
private static final SessionFactory sessionFactory; private static final SessionFactory sessionFactory;
static { static {

View File

@ -18,7 +18,6 @@
package com.wisemapping.service; package com.wisemapping.service;
import com.wisemapping.filter.SupportedUserAgent;
import com.wisemapping.model.Collaboration; import com.wisemapping.model.Collaboration;
import com.wisemapping.model.Mindmap; import com.wisemapping.model.Mindmap;
import com.wisemapping.model.User; import com.wisemapping.model.User;
@ -202,7 +201,7 @@ final public class NotificationService {
final String userEmail = user != null ? user.getEmail() : "'anonymous'"; final String userEmail = user != null ? user.getEmail() : "'anonymous'";
model.put("email", userEmail); model.put("email", userEmail);
model.put("userAgent", request.getHeader(SupportedUserAgent.USER_AGENT_HEADER)); model.put("userAgent", request.getHeader("User-Agent"));
model.put("server", request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort()); model.put("server", request.getScheme() + "://" + request.getServerName() + ":" + request.getServerPort());
model.put("requestURI", request.getRequestURI()); model.put("requestURI", request.getRequestURI());
model.put("method", request.getMethod()); model.put("method", request.getMethod());

View File

@ -50,6 +50,8 @@ logging:
# Application Configuration. # Application Configuration.
app: app:
api:
http-basic-enabled: false
jwt: jwt:
secret: dlqxKAg685SaKhsQXIMeM=JWCw3bkl3Ei3Tb7LMlnd19oMd66burPNlJ0Po1qguyjgpakQTk2CN3 secret: dlqxKAg685SaKhsQXIMeM=JWCw3bkl3Ei3Tb7LMlnd19oMd66burPNlJ0Po1qguyjgpakQTk2CN3
expirationMin: 10080 # One week expirationMin: 10080 # One week

View File

@ -40,7 +40,11 @@ import static com.wisemapping.test.rest.RestHelper.*;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest(classes = {RestAppConfig.class, CommonConfig.class, MindmapController.class, AdminController.class, UserController.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @SpringBootTest(
classes = {RestAppConfig.class, CommonConfig.class, MindmapController.class, AdminController.class, UserController.class},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {"app.api.http-basic-enabled=true"}
)
@AutoConfigureMockMvc @AutoConfigureMockMvc
public class RestAccountControllerTest { public class RestAccountControllerTest {
private static final String ADMIN_USER = "admin@wisemapping.org"; private static final String ADMIN_USER = "admin@wisemapping.org";

View File

@ -38,7 +38,10 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest(classes = {RestAppConfig.class, CommonConfig.class, JwtAuthController.class}) @SpringBootTest(
classes = {RestAppConfig.class, CommonConfig.class, JwtAuthController.class},
properties = {"app.api.http-basic-enabled=true"}
)
@AutoConfigureMockMvc @AutoConfigureMockMvc
public class RestJwtAuthControllerTest { public class RestJwtAuthControllerTest {

View File

@ -28,7 +28,10 @@ import static com.wisemapping.test.rest.RestHelper.createHeaders;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest(classes = {RestAppConfig.class, CommonConfig.class, LabelController.class, AdminController.class, UserController.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @SpringBootTest(
classes = {RestAppConfig.class, CommonConfig.class, LabelController.class, AdminController.class, UserController.class},
properties = {"app.api.http-basic-enabled=true"},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class RestLabelControllerTest { public class RestLabelControllerTest {
private static final String COLOR = "#000000"; private static final String COLOR = "#000000";

View File

@ -31,7 +31,10 @@ import java.util.stream.Collectors;
import static com.wisemapping.test.rest.RestHelper.createHeaders; import static com.wisemapping.test.rest.RestHelper.createHeaders;
import static org.junit.jupiter.api.Assertions.*; import static org.junit.jupiter.api.Assertions.*;
@SpringBootTest(classes = {RestAppConfig.class, CommonConfig.class, MindmapController.class, AdminController.class, UserController.class}, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @SpringBootTest(
classes = {RestAppConfig.class, CommonConfig.class, MindmapController.class, AdminController.class, UserController.class},
webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
properties = {"app.api.http-basic-enabled=true"})
public class RestMindmapControllerTest { public class RestMindmapControllerTest {
private RestUser user; private RestUser user;

View File

@ -45,7 +45,10 @@ import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
@SpringBootTest(classes = {RestAppConfig.class, CommonConfig.class, UserController.class}) @SpringBootTest(
classes = {RestAppConfig.class, CommonConfig.class, UserController.class},
properties = {"app.api.http-basic-enabled=true"}
)
@AutoConfigureMockMvc @AutoConfigureMockMvc
public class RestUserControllerTest { public class RestUserControllerTest {