Refactor API URLs to use GlobalConstants and update CORS configurations for production

This commit is contained in:
liosha84
2025-07-28 13:15:44 +03:00
parent 88f0cf307e
commit c58dd4ac5c
45 changed files with 587 additions and 72 deletions
@@ -1,5 +1,6 @@
package com.jambotronGroup.jambotron;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
@@ -7,6 +8,7 @@ import org.slf4j.event.Level;
import org.slf4j.helpers.BasicMarker;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Import;
import java.util.Iterator;
@@ -19,9 +21,9 @@ public class JambotronApplication {
SpringApplication.run(JambotronApplication.class, args);
logger.error("Application Run.");
logger.debug("Application Run.");
logger.info("Application Run.");
logger.error("Application Run. This is an error message.");
logger.debug("Application Run. This is a debug message.");
logger.info("Application Run. This is an info message.");
}
}
@@ -12,13 +12,13 @@ import org.springframework.web.bind.annotation.*;
import java.util.List;
@CrossOrigin(origins = "http://localhost:4200, https://pony-sincere-chimp.ngrok-free.app/",
maxAge = 3600,
allowCredentials="true",
allowedHeaders = {"Content-Type", "Authorization", "X-Requested-With"}
)
//@CrossOrigin(origins = "http://localhost:4200, https://pony-sincere-chimp.ngrok-free.app/",
// maxAge = 3600,
// allowCredentials="true",
// allowedHeaders = {"Content-Type", "Authorization", "X-Requested-With"}
//)
@RestController
@RequestMapping("/api/zhipuai")
@RequestMapping("/api/public/zhipuai")
public class ImageController {
@Autowired
@@ -32,7 +32,7 @@ import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
//@CrossOrigin(origins = "*", maxAge = 3600)
@CrossOrigin(origins = "http://localhost:4200,https://a576-5-248-149-207.ngrok-free.app, https://pony-sincere-chimp.ngrok-free.app", maxAge = 3600, allowCredentials="true")
//@CrossOrigin(origins = "http://localhost:4200,https://a576-5-248-149-207.ngrok-free.app, https://pony-sincere-chimp.ngrok-free.app", maxAge = 3600, allowCredentials="true")
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@@ -20,7 +20,7 @@ import java.time.LocalDateTime;
import java.util.*;
//@CrossOrigin(origins = "http://localhost:4200", maxAge = 3600, allowCredentials="true")
//@CrossOrigin(origins = "http://localhost:4200,http://www.jambotron.run.place", maxAge = 3600, allowCredentials="true")
@RestController
@RequestMapping("/api")
public class TutorialController {
@@ -98,10 +98,10 @@ public class TutorialController {
@PostMapping("user/tutorial-add")
public ResponseEntity<Tutorial> createTutorial(@RequestBody Tutorial tutorial) {
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
// not work from white IP port 80 to docker container port 8080 or 8081
//UserDetails userDetails = authenticationFacade.getUserDetails();
User user = userRepository.findById(((UserDetailsImpl)userDetails).getId()).get();
User user = authenticationFacade.getUser();
try {
Tutorial newTutorial =new Tutorial(
@@ -1,29 +1,76 @@
package com.jambotronGroup.jambotron.security;
import com.jambotronGroup.jambotron.controllers.AuthController;
import com.jambotronGroup.jambotron.model.User;
import com.jambotronGroup.jambotron.repository.UserRepository;
import com.jambotronGroup.jambotron.security.services.UserDetailsImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class AuthenticationFacade implements IAuthenticationFacade {
private static final Logger logger = LoggerFactory.getLogger(AuthenticationFacade.class);
@Autowired
UserRepository userRepository;
@Override
public Authentication getAuthentication() {
return SecurityContextHolder.getContext().getAuthentication();
}
//Deprecated method, use getUser() instead
@Override
public UserDetailsImpl getUserDetails() {
logger.warn("Retrieving user details from the security context");
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
if (authentication == null || !authentication.isAuthenticated()) {
throw new IllegalStateException("No authenticated user found");
}
if (!(authentication.getPrincipal() instanceof UserDetails)) {
throw new IllegalStateException("Authentication principal is not an instance of UserDetails");
}
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
if (!(userDetails instanceof UserDetailsImpl)) {
throw new IllegalStateException("UserDetails is not an instance of UserDetailsImpl");
}
return (UserDetailsImpl) userDetails;
}
@Override
public com.jambotronGroup.jambotron.model.User getUser() {
User returnValue = null;
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
if (!(authentication.getPrincipal() instanceof UserDetails)) {
logger.info("Authentication principal is not an instance of UserDetails, returning null");
logger.info(authentication.toString());
Optional<User> user = userRepository.findByUsername(authentication.getPrincipal().toString());
returnValue = user.get();
}else{
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
UserDetailsImpl userDetailsImpl = (UserDetailsImpl) userDetails;
returnValue = userRepository.findById(userDetailsImpl.getId()).get();
}
return returnValue;
}
}
@@ -1,5 +1,6 @@
package com.jambotronGroup.jambotron.security;
import com.jambotronGroup.jambotron.model.User;
import com.jambotronGroup.jambotron.security.services.UserDetailsImpl;
import org.springframework.security.core.Authentication;
@@ -7,4 +8,6 @@ public interface IAuthenticationFacade {
Authentication getAuthentication();
UserDetailsImpl getUserDetails();
User getUser();
}
@@ -0,0 +1,41 @@
package com.jambotronGroup.jambotron.security;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpMethod;
import org.springframework.stereotype.Component;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;
import java.io.IOException;
/*
@Configuration
public class MyCorsFilterConfig extends CorsFilter {
public MyCorsFilterConfig(CorsConfigurationSource source) {
super((CorsConfigurationSource) source);
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
throws ServletException, IOException {
response.addHeader("Access-Control-Allow-Headers",
"Access-Control-Allow-Origin, Origin, Accept, X-Requested-With, Content-Type, Access-Control-Request-Method, Access-Control-Request-Headers");
if (response.getHeader("Access-Control-Allow-Origin") == null)
response.addHeader("Access-Control-Allow-Origin", "http://localhost:4200");
if(!request.getRequestURI().startsWith("/api/auth")) {
response.addHeader("Access-Control-Allow-Credentials", "true");
}
filterChain.doFilter(request, response);
}
}
*/
@@ -0,0 +1,43 @@
package com.jambotronGroup.jambotron.security;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import java.util.List;
/*
@Configuration
public class RestConfig {
@Bean
public MyCorsFilterConfig corsFilter() {
CorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:4200,http://www.jambotron.run.place");
config.addAllowedMethod(HttpMethod.DELETE);
config.addAllowedMethod(HttpMethod.GET);
config.addAllowedMethod(HttpMethod.OPTIONS);
config.addAllowedMethod(HttpMethod.PUT);
config.addAllowedMethod(HttpMethod.POST);
// ((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**", config);
config = new CorsConfiguration();
config.setAllowCredentials(false);
config.setAllowedOrigins(List.of("http://localhost:4200","http://www.jambotron.run.place"));
config.addAllowedMethod(HttpMethod.DELETE);
config.addAllowedMethod(HttpMethod.GET);
config.addAllowedMethod(HttpMethod.OPTIONS);
config.addAllowedMethod(HttpMethod.PUT);
config.addAllowedMethod(HttpMethod.POST);
config.addAllowedHeader("*");
((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("api/auth/**", config);
return new MyCorsFilterConfig(source);
}
}*/
@@ -5,12 +5,14 @@ import com.jambotronGroup.jambotron.security.jwt.AuthTokenFilter;
import com.jambotronGroup.jambotron.security.services.UserDetailsServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityCustomizer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@@ -22,6 +24,8 @@ import org.springframework.web.filter.CorsFilter;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import static org.springframework.security.config.Customizer.withDefaults;
@Configuration
@EnableMethodSecurity
//@EnableWebSecurity
@@ -29,6 +33,7 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
// securedEnabled = true,
// jsr250Enabled = true,
//prePostEnabled = true)
@ComponentScan("com.jambotronGroup.jambotron.security")
public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsServiceImpl userDetailsService;
@@ -57,7 +62,6 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
return authProvider;
}
// @Bean
// @Override
// public AuthenticationManager authenticationManagerBean() throws Exception {
@@ -106,12 +110,39 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http.csrf(csrf -> csrf.disable()).cors(cors -> cors.disable())
http.csrf(csrf -> csrf.disable())//cors.configurationSource(corsCongigSource()))
.exceptionHandling(exception -> exception.authenticationEntryPoint(unauthorizedHandler))
.sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.authorizeHttpRequests(auth ->
auth.requestMatchers("/api/auth/**").permitAll()
.requestMatchers("/*", "/home", "/resources/**").permitAll()
.authorizeHttpRequests(auth ->auth
// Access without authentication
// Allow public access to the root and home pages
.requestMatchers("/*").permitAll()
.requestMatchers("/resources/**").permitAll()
.requestMatchers("/api/auth/**").permitAll()
// Allow public access to tutorials (without login)
.requestMatchers("/api/public/tutorials").permitAll()
//.requestMatchers("/api/public/tutorials/**").permitAll()
//TODO: need check the puth
.requestMatchers("/api/public/zhipuai/image/**").permitAll()
// need for cerbot why i don't know
.requestMatchers("/.well-known/acme-challenge/**").permitAll()
// Access permitted for specific roles
.requestMatchers("/api/user/**").hasRole("USER")
.requestMatchers("/api/moderator/**").hasRole("MODERATOR")
.requestMatchers("/api/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
/* // Allow access to specific API endpoints without authentication
.requestMatchers("/api/auth/**").permitAll()
// Allow access to specific resources
.requestMatchers("/*", "/home", "/resources/**").permitAll()
.requestMatchers("/resources/public/media/**").permitAll()
.requestMatchers("/resources/public/browser/**").permitAll()
.requestMatchers("/media/**").permitAll()
@@ -121,7 +152,7 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
.requestMatchers("/api/tutorials").permitAll()
.requestMatchers("/api/zhipuai/image/**").permitAll()
.requestMatchers("/api/users").permitAll()
.requestMatchers("/api/users/**").permitAll()
@@ -133,16 +164,10 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
.requestMatchers("/api/settings").permitAll()
.requestMatchers("/api/system/**").permitAll()
*/
// Allow public access to tutorials (without login)
.requestMatchers("/api/public/tutorials").permitAll()
.requestMatchers("/api/public/tutorials/**").permitAll()
.requestMatchers("/api/user/**").permitAll()
.requestMatchers("/api/moderator/**").permitAll()
.anyRequest().authenticated()
);
).redirectToHttps(withDefaults());
http.authenticationProvider(authenticationProvider());
@@ -151,17 +176,77 @@ public class WebSecurityConfig implements WebMvcConfigurer {// extends WebSecuri
return http.build();
}
@Bean
/*@Bean
public CorsFilter corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
config.addAllowedOrigin("http://localhost:4200");
// config.setAllowCredentials(true);
// config.addAllowedOrigin("http://localhost:4200");
// config.addAllowedHeader("*");
// config.addAllowedMethod("*");
// source.registerCorsConfiguration("/**", config);
//
// config = new CorsConfiguration();
// config.setAllowCredentials(true);
// config.addAllowedOrigin("http://213.111.120.199");
// config.addAllowedHeader("*");
// config.addAllowedMethod("*");
// source.registerCorsConfiguration("/**", config);
// config = new CorsConfiguration();
// config.setAllowCredentials(false);
// config.addAllowedOrigin("http://www.jambotron.run.place");
// config.addAllowedHeader("*");
// config.addAllowedMethod("*");
// source.registerCorsConfiguration("/**", config);
config = new CorsConfiguration();
config.setAllowCredentials(false);
config.addAllowedOrigin("http://www.jambotron.run.place");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/**", config);
source.registerCorsConfiguration("/api/user/**", config);
return new CorsFilter(source);
}
}*/
/* public UrlBasedCorsConfigurationSource corsCongigSource() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
// config.setAllowCredentials(true);
// config.addAllowedOrigin("http://localhost:4200");
// config.addAllowedHeader("*");
// config.addAllowedMethod("*");
// source.registerCorsConfiguration("/**", config);
//
// config = new CorsConfiguration();
// config.setAllowCredentials(true);
// config.addAllowedOrigin("http://213.111.120.199");
// config.addAllowedHeader("*");
// config.addAllowedMethod("*");
// source.registerCorsConfiguration("/**", config);
// config = new CorsConfiguration();
// config.setAllowCredentials(false);
// config.addAllowedOrigin("http://www.jambotron.run.place");
// config.addAllowedHeader("*");
// config.addAllowedMethod("*");
// source.registerCorsConfiguration("/**", config);
config = new CorsConfiguration();
config.setAllowCredentials(false);
config.addAllowedOrigin("http://localhost:4200, http://www.jambotron.run.place");
config.addAllowedHeader("*");
config.addAllowedMethod("*");
source.registerCorsConfiguration("/api/user/**", config);
return source;
}*/
/* @Bean
public WebSecurityCustomizer webSecurityCustomizer() {
return (web) -> web.ignoring().requestMatchers("/images/**", "/js/**", "/webjars/**");
}*/
}
@@ -9,7 +9,9 @@ import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
@@ -19,6 +21,9 @@ import java.io.IOException;
public class AuthTokenFilter extends OncePerRequestFilter {
@Autowired
AuthenticationManager authenticationManager;
@Autowired
private JwtUtils jwtUtils;
@@ -35,8 +40,15 @@ public class AuthTokenFilter extends OncePerRequestFilter {
if (jwt != null && jwtUtils.validateJwtToken(jwt)) {
String username = jwtUtils.getUserNameFromJwtToken(jwt);
logger.warn("Username from JWT: {}", username);
UserDetails userDetails = userDetailsService.loadUserByUsername(username);
// Authentication authentication = authenticationManager.authenticate(
// new UsernamePasswordAuthenticationToken(userDetails.getUsername(),userDetails.getPassword()));
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(userDetails,
null,
@@ -40,6 +40,8 @@ public class UserDetailsImpl implements UserDetails {
.map(role -> new SimpleGrantedAuthority(role.getName().name()))
.collect(Collectors.toList());
return new UserDetailsImpl(
user.getId(),
user.getUsername(),
@@ -23,6 +23,8 @@ public class UserDetailsServiceImpl implements UserDetailsService {
.orElseThrow(() -> new UsernameNotFoundException("User Not Found with username: " + username));
return UserDetailsImpl.build(user);
// UserDetailsImpl userDetails = UserDetailsImpl.build(user);
// return new org.springframework.security.core.userdetails.User(userDetails.getUsername(), userDetails.getPassword(), userDetails.getAuthorities());
}
}