Skip to content

Commit

Permalink
Fix CERN lifecycle handler (#871)
Browse files Browse the repository at this point in the history
* Consider null end date as unlimited membership
* Manage 404 response from hr db api service
* Configurable behavior in case VO Person or CERN person id are not found
* Simplify API exceptions management
  • Loading branch information
enricovianello authored Nov 22, 2024
1 parent f628b97 commit 8836869
Show file tree
Hide file tree
Showing 15 changed files with 789 additions and 250 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,24 @@
*/
package it.infn.mw.iam.api.registration.cern;

import java.util.Optional;

import org.springframework.context.annotation.Profile;
import org.springframework.web.client.RestClientException;

import it.infn.mw.iam.api.registration.cern.dto.VOPersonDTO;

@Profile("cern")
public interface CernHrDBApiService {

VOPersonDTO getHrDbPersonRecord(String personId);
/**
* Returns an @Optional object that contains the @VOPersonDTO related to the CERN person ID
* provided as parameter or empty if not found.
*
* @param personId
* @return
* @throws RestClientException in case of ApiErrors
*/
Optional<VOPersonDTO> getHrDbPersonRecord(String personId) throws RestClientException;

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@

import static it.infn.mw.iam.util.BasicAuthenticationUtils.basicAuthHeaderValue;
import static java.lang.String.format;
import static org.springframework.http.HttpStatus.NOT_FOUND;

import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -26,6 +29,7 @@
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

Expand Down Expand Up @@ -63,7 +67,7 @@ private HttpHeaders buildAuthHeaders() {
}

@Override
public VOPersonDTO getHrDbPersonRecord(String personId) {
public Optional<VOPersonDTO> getHrDbPersonRecord(String personId) {

RestTemplate rt = rtFactory.newRestTemplate();

Expand All @@ -75,10 +79,13 @@ public VOPersonDTO getHrDbPersonRecord(String personId) {
try {
ResponseEntity<VOPersonDTO> response = rt.exchange(personValidUrl, HttpMethod.GET,
new HttpEntity<>(buildAuthHeaders()), VOPersonDTO.class);
return response.getBody();
return Optional.of(response.getBody());
} catch (RestClientException e) {
final String errorMsg = "HR db api error: " + e.getMessage();
throw new CernHrDbApiError(errorMsg, e);
if ((e instanceof HttpClientErrorException)
&& (((HttpClientErrorException) e).getStatusCode().equals(NOT_FOUND))) {
return Optional.empty();
}
throw new CernHrDbApiError(e.getMessage(), e);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import java.time.Instant;
import java.util.Date;
import java.util.Optional;

import javax.servlet.http.HttpSession;

Expand Down Expand Up @@ -69,7 +70,7 @@ public String mockCernAuthentication(HttpSession session) {
}

@Override
public VOPersonDTO getHrDbPersonRecord(String personId) {
public Optional<VOPersonDTO> getHrDbPersonRecord(String personId) {
VOPersonDTO dto = new VOPersonDTO();
dto.setFirstName("TEST");
dto.setName("USER");
Expand All @@ -89,6 +90,6 @@ public VOPersonDTO getHrDbPersonRecord(String personId) {
p.setInstitute(i);

dto.getParticipations().add(p);
return dto;
return Optional.of(dto);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

public class DefaultRestTemplateFactory implements RestTemplateFactory {

private ClientHttpRequestFactory httpRequestFactory;
final ClientHttpRequestFactory httpRequestFactory;

public DefaultRestTemplateFactory(ClientHttpRequestFactory httpRequestFactory) {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@

import javax.validation.Valid;
import javax.validation.constraints.Min;

import javax.validation.constraints.NotBlank;

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.annotation.Validated;
Expand Down Expand Up @@ -100,6 +100,10 @@ public void setPassword(String password) {
}
}

public enum CernHrActionsOnUser {
NO_ACTION, DISABLE_USER;
}

@NotBlank
private String ssoIssuer = "https://auth.cern.ch/auth/realms/cern";

Expand All @@ -109,6 +113,10 @@ public void setPassword(String password) {
@NotBlank
private String experimentName = "test";

private CernHrActionsOnUser onPersonIdNotFound = CernHrActionsOnUser.NO_ACTION;

private CernHrActionsOnUser onParticipationNotFound = CernHrActionsOnUser.NO_ACTION;

@Valid
private HrDbApiProperties hrApi = new HrDbApiProperties();

Expand Down Expand Up @@ -154,4 +162,21 @@ public HrSynchTaskProperties getTask() {
public void setTask(HrSynchTaskProperties task) {
this.task = task;
}

public CernHrActionsOnUser getOnPersonIdNotFound() {
return onPersonIdNotFound;
}

public void setOnPersonIdNotFound(CernHrActionsOnUser onPersonIdNotFound) {
this.onPersonIdNotFound = onPersonIdNotFound;
}

public CernHrActionsOnUser getOnParticipationNotFound() {
return onParticipationNotFound;
}

public void setOnParticipationNotFound(CernHrActionsOnUser onParticipationNotFound) {
this.onParticipationNotFound = onParticipationNotFound;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public class OidcConfiguration {
public static final String DEFINE_ME_PLEASE = "define_me_please";

@Bean
public FilterRegistrationBean<OidcClientFilter> disabledAutomaticOidcFilterRegistration(
FilterRegistrationBean<OidcClientFilter> disabledAutomaticOidcFilterRegistration(
OidcClientFilter f) {

FilterRegistrationBean<OidcClientFilter> b = new FilterRegistrationBean<>(f);
Expand All @@ -103,7 +103,7 @@ public FilterRegistrationBean<OidcClientFilter> disabledAutomaticOidcFilterRegis
}

@Bean(name = "OIDCAuthenticationFilter")
public OidcClientFilter openIdConnectAuthenticationFilterCanl(OidcTokenRequestor tokenRequestor,
OidcClientFilter openIdConnectAuthenticationFilterCanl(OidcTokenRequestor tokenRequestor,
@Qualifier("OIDCAuthenticationManager") AuthenticationManager oidcAuthenticationManager,
@Qualifier("OIDCExternalAuthenticationSuccessHandler") AuthenticationSuccessHandler successHandler,
@Qualifier("OIDCExternalAuthenticationFailureHandler") AuthenticationFailureHandler failureHandler,
Expand All @@ -129,27 +129,27 @@ public OidcClientFilter openIdConnectAuthenticationFilterCanl(OidcTokenRequestor

@Bean
@Profile("!canl")
public RestTemplateFactory restTemplateFactory() {
RestTemplateFactory restTemplateFactory() {

return new DefaultRestTemplateFactory(new HttpComponentsClientHttpRequestFactory());
}

@Bean
@Profile("canl")
public RestTemplateFactory canlRestTemplateFactory(
RestTemplateFactory canlRestTemplateFactory(
@Qualifier("canlRequestFactory") ClientHttpRequestFactory rf) {

return new DefaultRestTemplateFactory(rf);
}

@Bean(name = "OIDCExternalAuthenticationFailureHandler")
public AuthenticationFailureHandler failureHandler() {
AuthenticationFailureHandler failureHandler() {

return new ExternalAuthenticationFailureHandler(new OidcExceptionMessageHelper());
}

@Bean(name = "OIDCExternalAuthenticationSuccessHandler")
public AuthenticationSuccessHandler successHandler() {
AuthenticationSuccessHandler successHandler() {

RootIsDashboardSuccessHandler sa =
new RootIsDashboardSuccessHandler(iamBaseUrl, new HttpSessionRequestCache());
Expand All @@ -161,13 +161,13 @@ public AuthenticationSuccessHandler successHandler() {
}

@Bean(name = "OIDCAuthenticationManager")
public AuthenticationManager authenticationManager(
AuthenticationManager authenticationManager(
OIDCAuthenticationProvider oidcAuthenticationProvider) {
return new ProviderManager(Arrays.asList(oidcAuthenticationProvider));
}

@Bean
public OIDCAuthenticationProvider openIdConnectAuthenticationProvider(Clock clock,
OIDCAuthenticationProvider openIdConnectAuthenticationProvider(Clock clock,
OidcUserDetailsService userDetailService, UserInfoFetcher userInfoFetcher,
AuthenticationValidator<OIDCAuthenticationToken> validator, SessionTimeoutHelper timeoutHelper) {

Expand All @@ -180,21 +180,21 @@ public OIDCAuthenticationProvider openIdConnectAuthenticationProvider(Clock cloc
}

@Bean
public IssuerService oidcIssuerService() {
IssuerService oidcIssuerService() {

return new IamThirdPartyIssuerService();
}

@Bean
@Profile("!canl")
public ServerConfigurationService dynamicServerConfiguration() {
ServerConfigurationService dynamicServerConfiguration() {

return new DynamicServerConfigurationService();
}

@Bean
@Profile("canl")
public ServerConfigurationService canlDynamicServerConfiguration(
ServerConfigurationService canlDynamicServerConfiguration(
@Qualifier("canlHttpClient") HttpClient client) {

return new DynamicServerConfigurationService(client);
Expand All @@ -205,7 +205,7 @@ public boolean configuredProvider(OidcProvider provider) {
}

@Bean
public ClientConfigurationService oidcClientConfiguration(OidcValidatedProviders providers) {
ClientConfigurationService oidcClientConfiguration(OidcValidatedProviders providers) {

Map<String, RegisteredClient> clients = new LinkedHashMap<>();

Expand All @@ -231,31 +231,31 @@ public ClientConfigurationService oidcClientConfiguration(OidcValidatedProviders
}

@Bean
public AuthRequestOptionsService authOptions() {
AuthRequestOptionsService authOptions() {

return new StaticAuthRequestOptionsService();
}

@Bean
public AuthRequestUrlBuilder authRequestBuilder() {
AuthRequestUrlBuilder authRequestBuilder() {

return new PlainAuthRequestUrlBuilder();
}

@Bean
public OidcUserDetailsService userDetailService(IamAccountRepository repo,
OidcUserDetailsService userDetailService(IamAccountRepository repo,
InactiveAccountAuthenticationHander handler) {

return new DefaultOidcUserDetailsService(repo, handler);
}

@Bean
public UserInfoFetcher userInfoFetcher() {
UserInfoFetcher userInfoFetcher() {
return new UserInfoFetcher();
}

@Bean
public OidcTokenRequestor tokenRequestor(RestTemplateFactory restTemplateFactory,
OidcTokenRequestor tokenRequestor(RestTemplateFactory restTemplateFactory,
ObjectMapper mapper) {
return new DefaultOidcTokenRequestor(restTemplateFactory, mapper);
}
Expand Down
Loading

0 comments on commit 8836869

Please sign in to comment.