Skip to content

Commit

Permalink
Improve ootb user experience and fix minor errors (#1016)
Browse files Browse the repository at this point in the history
  • Loading branch information
gitCarrot authored Sep 20, 2024
1 parent 2241543 commit 06140dd
Show file tree
Hide file tree
Showing 11 changed files with 340 additions and 322 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import edu.hawaii.its.api.service.HttpRequestService;
import edu.hawaii.its.api.service.OotbHttpRequestService;
import edu.hawaii.its.groupings.access.UserContextService;
import edu.hawaii.its.groupings.configuration.OotbStaticUserAuthenticationFilter;
Expand All @@ -28,29 +27,24 @@
@RequestMapping("/api/groupings/ootb")
public class OotbRestController {
private static final Log logger = LogFactory.getLog(OotbRestController.class);
private final PolicyFactory policy = Sanitizers.FORMATTING;;

@Value("${url.api.2.1.base}")
private String API_2_1_BASE;

private final PolicyFactory policy = Sanitizers.FORMATTING;
private final UserContextService userContextService;

private final OotbStaticUserAuthenticationFilter ootbAuthenticationFilter;

private final OotbActiveUserProfileService ootbActiveUserProfileService;

private final OotbHttpRequestService ootbHttpRequestService;
private final OotbStaticUserAuthenticationFilter ootbAuthenticationFilter;

@Value("${url.api.2.1.base}")
private String API_2_1_BASE;

// Constructor.
public OotbRestController(UserContextService userContextService,
OotbStaticUserAuthenticationFilter ootbAuthenticationFilter,
OotbActiveUserProfileService ootbActiveUserProfileService,
OotbHttpRequestService ootbHttpRequestService) {
OotbHttpRequestService ootbHttpRequestService, OotbStaticUserAuthenticationFilter ootbAuthenticationFilter1) {
this.userContextService = userContextService;
this.ootbAuthenticationFilter = ootbAuthenticationFilter;
this.ootbActiveUserProfileService = ootbActiveUserProfileService;
this.ootbHttpRequestService = ootbHttpRequestService;
this.ootbAuthenticationFilter = ootbAuthenticationFilter1;
}

/*
Expand All @@ -67,8 +61,8 @@ public ResponseEntity<List<String>> getAvailableProfiles() {
@PostMapping(value = "/{activeProfile}")
public ResponseEntity<OotbActiveProfile> updateActiveDefaultUser(@PathVariable String activeProfile) {
String currentUid = policy.sanitize(userContextService.getCurrentUid());
ootbAuthenticationFilter.setUserProfile(activeProfile);
OotbActiveProfile ootbActiveProfile = ootbActiveUserProfileService.getActiveProfiles().get(activeProfile);
ootbAuthenticationFilter.setUserProfile(activeProfile);
String baseUri = API_2_1_BASE + "/activeProfile/ootb";
return ootbHttpRequestService.makeApiRequestWithActiveProfileBody(currentUid, baseUri, ootbActiveProfile,
HttpMethod.POST);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,52 +3,50 @@
import static org.springframework.security.config.Customizer.withDefaults;
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;

import java.util.List;
import jakarta.annotation.PostConstruct;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.ws.config.annotation.DelegatingWsConfiguration;

import edu.hawaii.its.api.controller.OotbRestController;
import edu.hawaii.its.groupings.access.DelegatingAuthenticationFailureHandler;
import edu.hawaii.its.groupings.service.OotbActiveUserProfileService;

@EnableWebSecurity
@Configuration
@ConditionalOnProperty(name = "grouping.api.server.type", havingValue = "OOTB")
@Profile("ootb")
public class OotbSecurityConfig {

private static final Log logger = LogFactory.getLog(OotbSecurityConfig.class);
private String userProfile;

@Value("${ootb.profiles.filename}")
private String profilesFileName;

private final OotbRestController ootbRestController;
private final OotbStaticUserAuthenticationFilter ootbStaticUserAuthenticationFilter;
private final OotbActiveUserProfileService ootbActiveUserProfileService;
@Value("${url.base}")
private String appUrlBase;

@Bean
public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration,
UserDetailsService userDetailsService) throws Exception {
DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
provider.setUserDetailsService(userDetailsService);
provider.setPasswordEncoder(passwordEncoder());
return new ProviderManager(List.of(provider));
public OotbSecurityConfig(OotbRestController ootbRestController,
OotbStaticUserAuthenticationFilter ootbStaticUserAuthenticationFilter,
OotbActiveUserProfileService ootbActiveUserProfileService) {
this.ootbRestController = ootbRestController;
this.ootbStaticUserAuthenticationFilter = ootbStaticUserAuthenticationFilter;
this.ootbActiveUserProfileService = ootbActiveUserProfileService;
}

@PostConstruct
public void init() {
updateActiveDefaultUser();
}

@Bean
Expand All @@ -69,7 +67,7 @@ public DelegatingWsConfiguration delegatingWsConfiguration() {
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.addFilterBefore(ootbStaticUserAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(ootbStaticUserAuthenticationFilter, UsernamePasswordAuthenticationFilter.class)
.authorizeHttpRequests((auths)
-> auths
.requestMatchers(antMatcher("/")).permitAll()
Expand Down Expand Up @@ -102,22 +100,7 @@ public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
return http.build();
}

@Bean
public OotbStaticUserAuthenticationFilter ootbStaticUserAuthenticationFilter() {
return new OotbStaticUserAuthenticationFilter(userDetailsService(), userProfile);
}

@Bean
public UserDetailsService userDetailsService() {
// Make Profile Service with JSON file that user sets in the properties file
OotbActiveUserProfileService ootbActiveUserProfileService = new OotbActiveUserProfileService(profilesFileName);

// Set the default profile to admin
setUserProfile(ootbActiveUserProfileService.findGivenNameForAdminRole());
return ootbActiveUserProfileService;
}

public void setUserProfile(String userProfile) {
this.userProfile = userProfile;
public void updateActiveDefaultUser() {
ootbRestController.updateActiveDefaultUser(ootbActiveUserProfileService.findGivenNameForAdminRole());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,34 +7,44 @@
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;

import org.springframework.context.annotation.Profile;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.filter.GenericFilterBean;

import edu.hawaii.its.groupings.service.OotbActiveUserProfileService;

@Service
@Profile("ootb")
public class OotbStaticUserAuthenticationFilter extends GenericFilterBean {

private final UserDetailsService userDetailsService;
private volatile String userProfile;
private final OotbActiveUserProfileService ootbActiveUserProfileService;

private String currentUserProfile;

public OotbStaticUserAuthenticationFilter(UserDetailsService userDetailsService, String userProfile) {
this.userProfile = userProfile;
this.userDetailsService = userDetailsService;
public OotbStaticUserAuthenticationFilter(
OotbActiveUserProfileService ootbActiveUserProfileService) {
this.ootbActiveUserProfileService = ootbActiveUserProfileService;
}

public void setUserProfile(String userProfile) {
this.userProfile = userProfile;
this.currentUserProfile = userProfile;
}

@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
if (SecurityContextHolder.getContext().getAuthentication() == null) {
UserDetails userDetails = userDetailsService.loadUserByUsername(userProfile);
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
UserDetails userDetails = ootbActiveUserProfileService.loadUserByUsername(
currentUserProfile);
if(userDetails != null) {
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
userDetails, null, userDetails.getAuthorities());
SecurityContextHolder.getContext().setAuthentication(authentication);
}
}
filterChain.doFilter(request, response);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
package edu.hawaii.its.groupings.configuration;

import edu.hawaii.its.groupings.access.CasUserDetailsServiceImpl;
import edu.hawaii.its.groupings.access.DelegatingAuthenticationFailureHandler;
import edu.hawaii.its.groupings.access.UserBuilder;
import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;

import jakarta.annotation.PostConstruct;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apereo.cas.client.proxy.ProxyGrantingTicketStorage;
import org.apereo.cas.client.proxy.ProxyGrantingTicketStorageImpl;
import org.apereo.cas.client.session.SingleSignOutFilter;
import org.apereo.cas.client.validation.Saml11TicketValidator;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.cas.ServiceProperties;
import org.springframework.security.cas.authentication.CasAssertionAuthenticationToken;
Expand All @@ -34,38 +34,32 @@
import org.springframework.util.Assert;
import org.springframework.ws.config.annotation.DelegatingWsConfiguration;

import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
import edu.hawaii.its.groupings.access.CasUserDetailsServiceImpl;
import edu.hawaii.its.groupings.access.DelegatingAuthenticationFailureHandler;
import edu.hawaii.its.groupings.access.UserBuilder;

@EnableWebSecurity
@Configuration
@ConditionalOnProperty(name = "grouping.api.server.type", havingValue = "GROUPER", matchIfMissing = true)
@Profile("!ootb")
public class SecurityConfig {

private static final Log logger = LogFactory.getLog(SecurityConfig.class);

private final UserBuilder userBuilder;
@Value("${url.base}")
private String appUrlBase;

@Value("${app.url.home}")
private String appUrlHome;

@Value("${cas.login.url}")
private String casLoginUrl;

@Value("${cas.logout.url}")
private String casLogoutUrl;

@Value("${cas.main.url}")
private String casMainUrl;

@Value("${cas.saml.tolerance}")
private long casSamlTolerance;

@Value("${cas.send.renew:false}")
private boolean casSendRenew;

private final UserBuilder userBuilder;

public SecurityConfig(UserBuilder userBuilder) {
this.userBuilder = userBuilder;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package edu.hawaii.its.groupings.controller;

import java.util.Arrays;
import java.util.Locale;
import java.util.Map;

Expand All @@ -9,6 +10,7 @@
import org.apache.commons.logging.LogFactory;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.env.Environment;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
Expand All @@ -20,6 +22,7 @@
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import edu.hawaii.its.groupings.access.UserContextService;
import edu.hawaii.its.groupings.configuration.Realm;
import edu.hawaii.its.groupings.service.EmailService;
import edu.hawaii.its.groupings.type.Feedback;

Expand All @@ -38,15 +41,21 @@ public class HomeController {

private final UserContextService userContextService;

public HomeController(EmailService emailService, UserContextService userContextService) {
private final Realm realmService;

public HomeController(EmailService emailService, UserContextService userContextService, Realm realmService) {
this.emailService = emailService;
this.userContextService = userContextService;
this.realmService = realmService;
}

// Mapping to home.
@GetMapping(value = { "/", "/home" })
public String home(Map<String, Locale> locale) {
logger.info("User at home. The client locale is " + locale);
if (realmService.isOotb()) {
return "redirect:/login";
}
return "home";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@
import java.util.Map;
import java.util.Optional;

import jakarta.annotation.PostConstruct;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Profile;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
Expand All @@ -17,26 +21,24 @@
import edu.hawaii.its.groupings.util.JsonUtil;

@Service
@Profile("ootb")
public class OotbActiveUserProfileService implements UserDetailsService {

@Value("${ootb.profiles.filename}")
private String profilesFileName;

// User is for SecurityContextHolder in AuthenticationFilter in UI project
private final Map<String, User> users = new LinkedHashMap<>();

// OotbActiveProfile is for request body to make api request
private final Map<String, OotbActiveProfile> activeProfiles = new LinkedHashMap<>();

// Default JSON file for active profiles
private String profilesFileName = "ootb.active.user.profiles.json";

public OotbActiveUserProfileService() {
initUsers();
}
public OotbActiveUserProfileService() {}

public OotbActiveUserProfileService(String profilesFileName) {
this.profilesFileName = profilesFileName;
initUsers();
}

@PostConstruct
private void initUsers() {
List<OotbActiveProfile> ootbActiveProfiles =
JsonUtil.asList(JsonUtil.readJsonFileToString(profilesFileName), OotbActiveProfile.class);
Expand Down
Loading

0 comments on commit 06140dd

Please sign in to comment.