From 4a59c3be487d63835bcc9959a6207aa47006a4bf Mon Sep 17 00:00:00 2001 From: davdarras Date: Tue, 18 Jun 2024 19:17:58 +0200 Subject: [PATCH 1/3] feat: add security infrastructure --- .gitignore | 8 +- .../{api => }/PearlJamApplication.java | 3 +- .../configuration/SpringDocConfiguration.java | 70 +---- .../api/configuration/auth/AuthConstants.java | 16 - .../api/configuration/auth/AuthorityRole.java | 35 --- .../configuration/auth/AuthorityRoleEnum.java | 9 - .../auth/GrantedAuthorityConverter.java | 46 --- .../auth/KeycloakSecurityConfiguration.java | 286 ------------------ .../auth/NoAuthSecurityConfiguration.java | 80 ----- .../auth/PublicSecurityFilterChain.java | 72 ----- .../api/configuration/log/LogInterceptor.java | 9 +- .../log}/PropertiesLogger.java | 24 +- .../properties/ApplicationProperties.java | 40 +-- .../api/controller/CampaignController.java | 103 +++---- .../controller/ClosingCauseController.java | 16 +- .../controller/ContactOutcomeController.java | 18 +- .../api/controller/InterviewerController.java | 40 ++- .../api/controller/MessageController.java | 45 ++- .../OrganizationUnitController.java | 39 +-- .../api/controller/PreferenceController.java | 10 +- .../api/controller/StateController.java | 33 +- .../api/controller/SurveyUnitController.java | 116 ++++--- .../api/controller/UserController.java | 46 +-- .../pearljam/api/service/UtilsService.java | 14 - .../impl/DataSetInjectorServiceImpl.java | 1 + .../api/service/impl/UserServiceImpl.java | 13 +- .../api/service/impl/UtilsServiceImpl.java | 25 -- .../authentication/AuthenticationHelper.java | 28 -- .../AuthenticationTokenException.java | 7 - .../AuthenticationUserHelper.java | 46 --- .../exception/ExceptionControllerAdvice.java | 9 - .../domain/security/model/AuthorityRole.java | 18 ++ .../AuthenticatedUserHelperPort.java | 28 ++ .../userside/AuthenticatedUserService.java | 29 ++ .../AuthenticationCurrentUserService.java | 29 ++ ...AuthenticatedCurrentUserHelperAdapter.java | 38 +++ .../config/GrantedAuthorityConverter.java | 54 ++++ .../config/NoAuthSecurityConfiguration.java | 110 +++++++ .../security/config/OidcProperties.java} | 8 +- .../config/OidcSecurityConfiguration.java | 271 +++++++++++++++++ .../config/SpringDocSecurityFilterChain.java | 46 +++ .../swagger/SpringDocNoAuthConfiguration.java | 19 ++ .../swagger/SpringDocOidcConfiguration.java | 59 ++++ .../SpringDocSecurityConfiguration.java | 14 + src/main/java/lombok.config | 2 +- src/main/resources/application-dev.properties | 21 -- src/main/resources/application.properties | 23 +- src/main/resources/dataset/delete_data.sql | 2 +- .../api/authKeycloak/TestAuthKeyCloak.java | 250 ++++++++------- .../controller/CampaignControllerTest.java | 16 +- .../insee/pearljam/api/noAuth/TestNoAuth.java | 69 ++--- .../service/dummy/CampaignFakeService.java | 12 +- .../utils/AuthenticatedUserTestHelper.java | 19 +- .../utils/dummy/AuthenticationFakeHelper.java | 25 -- .../dummy/AuthenticationUserFakeService.java | 26 ++ .../config/GrantedAuthorityConverterTest.java | 100 ++++++ ...properties => application-auth.properties} | 9 +- .../resources/application-noauth.properties | 46 +++ 58 files changed, 1355 insertions(+), 1295 deletions(-) rename src/main/java/fr/insee/pearljam/{api => }/PearlJamApplication.java (93%) delete mode 100644 src/main/java/fr/insee/pearljam/api/configuration/auth/AuthConstants.java delete mode 100644 src/main/java/fr/insee/pearljam/api/configuration/auth/AuthorityRole.java delete mode 100644 src/main/java/fr/insee/pearljam/api/configuration/auth/AuthorityRoleEnum.java delete mode 100644 src/main/java/fr/insee/pearljam/api/configuration/auth/GrantedAuthorityConverter.java delete mode 100644 src/main/java/fr/insee/pearljam/api/configuration/auth/KeycloakSecurityConfiguration.java delete mode 100644 src/main/java/fr/insee/pearljam/api/configuration/auth/NoAuthSecurityConfiguration.java delete mode 100644 src/main/java/fr/insee/pearljam/api/configuration/auth/PublicSecurityFilterChain.java rename src/main/java/fr/insee/pearljam/api/{ => configuration/log}/PropertiesLogger.java (68%) delete mode 100644 src/main/java/fr/insee/pearljam/api/web/authentication/AuthenticationHelper.java delete mode 100644 src/main/java/fr/insee/pearljam/api/web/authentication/AuthenticationTokenException.java delete mode 100644 src/main/java/fr/insee/pearljam/api/web/authentication/AuthenticationUserHelper.java create mode 100644 src/main/java/fr/insee/pearljam/domain/security/model/AuthorityRole.java create mode 100644 src/main/java/fr/insee/pearljam/domain/security/port/serverside/AuthenticatedUserHelperPort.java create mode 100644 src/main/java/fr/insee/pearljam/domain/security/port/userside/AuthenticatedUserService.java create mode 100644 src/main/java/fr/insee/pearljam/domain/security/service/AuthenticationCurrentUserService.java create mode 100644 src/main/java/fr/insee/pearljam/infrastructure/security/adapter/AuthenticatedCurrentUserHelperAdapter.java create mode 100644 src/main/java/fr/insee/pearljam/infrastructure/security/config/GrantedAuthorityConverter.java create mode 100644 src/main/java/fr/insee/pearljam/infrastructure/security/config/NoAuthSecurityConfiguration.java rename src/main/java/fr/insee/pearljam/{api/configuration/properties/KeycloakProperties.java => infrastructure/security/config/OidcProperties.java} (53%) create mode 100644 src/main/java/fr/insee/pearljam/infrastructure/security/config/OidcSecurityConfiguration.java create mode 100644 src/main/java/fr/insee/pearljam/infrastructure/security/config/SpringDocSecurityFilterChain.java create mode 100644 src/main/java/fr/insee/pearljam/infrastructure/security/config/swagger/SpringDocNoAuthConfiguration.java create mode 100644 src/main/java/fr/insee/pearljam/infrastructure/security/config/swagger/SpringDocOidcConfiguration.java create mode 100644 src/main/java/fr/insee/pearljam/infrastructure/security/config/swagger/SpringDocSecurityConfiguration.java delete mode 100644 src/main/resources/application-dev.properties delete mode 100644 src/test/java/fr/insee/pearljam/api/utils/dummy/AuthenticationFakeHelper.java create mode 100644 src/test/java/fr/insee/pearljam/api/utils/dummy/AuthenticationUserFakeService.java create mode 100644 src/test/java/fr/insee/pearljam/infrastructure/security/config/GrantedAuthorityConverterTest.java rename src/test/resources/{application-test.properties => application-auth.properties} (78%) create mode 100644 src/test/resources/application-noauth.properties diff --git a/.gitignore b/.gitignore index c26bf335..8872a5e5 100644 --- a/.gitignore +++ b/.gitignore @@ -29,9 +29,11 @@ build/ ### VS Code ### .vscode/ -/application-insee.properties + +**/.flattened-pom.xml +**/src/main/resources/application-*.yaml +**/src/main/resources/application-*.yml +**/src/main/resources/application-*.properties *.DS_Store /.apt_generated_tests/ - -/src/main/resources/application-dev.properties \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/api/PearlJamApplication.java b/src/main/java/fr/insee/pearljam/PearlJamApplication.java similarity index 93% rename from src/main/java/fr/insee/pearljam/api/PearlJamApplication.java rename to src/main/java/fr/insee/pearljam/PearlJamApplication.java index 844e14f3..265eebd8 100644 --- a/src/main/java/fr/insee/pearljam/api/PearlJamApplication.java +++ b/src/main/java/fr/insee/pearljam/PearlJamApplication.java @@ -1,5 +1,6 @@ -package fr.insee.pearljam.api; +package fr.insee.pearljam; +import fr.insee.pearljam.api.configuration.log.PropertiesLogger; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.context.event.ApplicationReadyEvent; diff --git a/src/main/java/fr/insee/pearljam/api/configuration/SpringDocConfiguration.java b/src/main/java/fr/insee/pearljam/api/configuration/SpringDocConfiguration.java index 75a26007..a970b222 100644 --- a/src/main/java/fr/insee/pearljam/api/configuration/SpringDocConfiguration.java +++ b/src/main/java/fr/insee/pearljam/api/configuration/SpringDocConfiguration.java @@ -1,82 +1,38 @@ package fr.insee.pearljam.api.configuration; -import java.util.List; - +import fr.insee.pearljam.infrastructure.security.config.swagger.SpringDocSecurityConfiguration; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.info.BuildProperties; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import fr.insee.pearljam.api.configuration.properties.ApplicationProperties; -import fr.insee.pearljam.api.configuration.properties.KeycloakProperties; -import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.OpenAPI; import io.swagger.v3.oas.models.info.Info; -import io.swagger.v3.oas.models.security.OAuthFlow; -import io.swagger.v3.oas.models.security.OAuthFlows; -import io.swagger.v3.oas.models.security.Scopes; -import io.swagger.v3.oas.models.security.SecurityRequirement; -import io.swagger.v3.oas.models.security.SecurityScheme; -import io.swagger.v3.oas.models.servers.Server; import lombok.RequiredArgsConstructor; /** - * SwaggerConfiguration is the class using to configure swagger 2 ways to - * authenticated : - without authentication, - keycloak authentication - * - * @author Claudel Benjamin - * + * Swagger configuration */ @Configuration @RequiredArgsConstructor +@ConditionalOnProperty(value="feature.swagger.enabled", havingValue = "true") public class SpringDocConfiguration { - public static final String SECURITY_SCHEMA_OAUTH2 = "oauth2"; - - @Bean - @ConditionalOnProperty(name = "application.auth", havingValue = "NOAUTH") - protected OpenAPI noAuthOpenAPI(BuildProperties buildProperties) { - return generateOpenAPI(buildProperties); - } + private final SpringDocSecurityConfiguration securityConfiguration; + /** + * Generate Open API configuration for springdoc + * @param buildProperties properties for build + * @return Open API configuration object + */ @Bean - @ConditionalOnProperty(name = "application.auth", havingValue = "KEYCLOAK") - protected OpenAPI keycloakOpenAPI(ApplicationProperties applicationProperties, - KeycloakProperties keycloakProperties, BuildProperties buildProperties) { - String authUrl = String.format("%s/realms/%s/protocol/openid-connect", - keycloakProperties.authServerUrl(), - keycloakProperties.realm()); - - return generateOpenAPI(buildProperties) - .addServersItem(new Server().url(applicationProperties.host())) - .addSecurityItem(new SecurityRequirement().addList(SECURITY_SCHEMA_OAUTH2, List.of("read", "write"))) - .components( - new Components() - .addSecuritySchemes(SECURITY_SCHEMA_OAUTH2, - new SecurityScheme() - .name(SECURITY_SCHEMA_OAUTH2) - .type(SecurityScheme.Type.OAUTH2) - .flows(getFlows(authUrl)))); - - } - - private OpenAPI generateOpenAPI(BuildProperties buildProperties) { - return new OpenAPI().info( + public OpenAPI generateOpenAPI(BuildProperties buildProperties) { + OpenAPI openAPI = new OpenAPI().info( new Info() .title(buildProperties.getName()) .description(buildProperties.get("description")) .version(buildProperties.getVersion())); + securityConfiguration.addSecurity(openAPI); + return openAPI; } - - private OAuthFlows getFlows(String authUrl) { - OAuthFlows flows = new OAuthFlows(); - OAuthFlow flow = new OAuthFlow(); - Scopes scopes = new Scopes(); - flow.setAuthorizationUrl(authUrl + "/auth"); - flow.setTokenUrl(authUrl + "/token"); - flow.setRefreshUrl(authUrl + "/token"); - flow.setScopes(scopes); - return flows.authorizationCode(flow); - } - } \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/api/configuration/auth/AuthConstants.java b/src/main/java/fr/insee/pearljam/api/configuration/auth/AuthConstants.java deleted file mode 100644 index 2ed4a027..00000000 --- a/src/main/java/fr/insee/pearljam/api/configuration/auth/AuthConstants.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.insee.pearljam.api.configuration.auth; - -public class AuthConstants { - private AuthConstants() { - throw new IllegalStateException("Constants class"); - } - - public static final String ROLE_PREFIX = "ROLE_"; - public static final String GUEST = "GUEST"; - public static final String ANONYMOUS = "ANONYMOUS"; - public static final String PREFERRED_USERNAME = "preferred_username"; - - public static final String generateAuthority(AuthorityRoleEnum are) { - return AuthConstants.ROLE_PREFIX + are; - } -} diff --git a/src/main/java/fr/insee/pearljam/api/configuration/auth/AuthorityRole.java b/src/main/java/fr/insee/pearljam/api/configuration/auth/AuthorityRole.java deleted file mode 100644 index a56d2386..00000000 --- a/src/main/java/fr/insee/pearljam/api/configuration/auth/AuthorityRole.java +++ /dev/null @@ -1,35 +0,0 @@ -package fr.insee.pearljam.api.configuration.auth; - -import static fr.insee.pearljam.api.configuration.auth.AuthorityRoleEnum.*; - -import java.util.stream.Collectors; -import java.util.stream.Stream; - -import org.springframework.security.core.Authentication; - -public class AuthorityRole { - private AuthorityRole() { - throw new IllegalArgumentException("Constant class"); - } - - private static String generateRoleExpression(AuthorityRoleEnum... roles) { - return Stream.of(roles) - .map(Enum::name) - .map(s -> String.format("'%s'", s)) - .collect(Collectors.joining(", ")); - } - - private static final String ANY_ROLE = generateRoleExpression(AuthorityRoleEnum.values()); - private static final String ADMIN_PRIVILEGES = generateRoleExpression(ADMIN, WEBCLIENT); - - public static final String HAS_ROLE_INTERVIEWER = String.format("hasRole(%s)", INTERVIEWER); - public static final String HAS_ANY_ROLE = String.format("hasAnyRole(%s)", ANY_ROLE); - public static final String HAS_ADMIN_PRIVILEGES = String.format("hasAnyRole(%s)", ADMIN_PRIVILEGES); - - public static final boolean autorityContainsRole(Authentication auth, AuthorityRoleEnum role) { - String targetAutority = AuthConstants.generateAuthority(role); - return auth.getAuthorities().stream() - .anyMatch(authority -> authority.getAuthority().equals(targetAutority)); - - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/api/configuration/auth/AuthorityRoleEnum.java b/src/main/java/fr/insee/pearljam/api/configuration/auth/AuthorityRoleEnum.java deleted file mode 100644 index b533bf28..00000000 --- a/src/main/java/fr/insee/pearljam/api/configuration/auth/AuthorityRoleEnum.java +++ /dev/null @@ -1,9 +0,0 @@ -package fr.insee.pearljam.api.configuration.auth; - -public enum AuthorityRoleEnum { - ADMIN, - WEBCLIENT, - LOCAL_USER, - NATIONAL_USER, - INTERVIEWER -} diff --git a/src/main/java/fr/insee/pearljam/api/configuration/auth/GrantedAuthorityConverter.java b/src/main/java/fr/insee/pearljam/api/configuration/auth/GrantedAuthorityConverter.java deleted file mode 100644 index 8ccd0414..00000000 --- a/src/main/java/fr/insee/pearljam/api/configuration/auth/GrantedAuthorityConverter.java +++ /dev/null @@ -1,46 +0,0 @@ -package fr.insee.pearljam.api.configuration.auth; - -import fr.insee.pearljam.api.configuration.properties.RoleProperties; -import lombok.AllArgsConstructor; - -import org.springframework.core.convert.converter.Converter; -import org.springframework.lang.NonNull; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.core.authority.SimpleGrantedAuthority; -import org.springframework.security.oauth2.jwt.Jwt; - -import java.util.*; -import java.util.stream.Collectors; - -@AllArgsConstructor -public class GrantedAuthorityConverter implements Converter> { - private static final String REALM_ACCESS_ROLE = "roles"; - private static final String REALM_ACCESS = "realm_access"; - - private final RoleProperties roleProperties; - - @SuppressWarnings("unchecked") - @Override - public Collection convert(@NonNull Jwt jwt) { - Map claims = jwt.getClaims(); - Map realmAccess = (Map) claims.get(REALM_ACCESS); - List roles = (List) realmAccess.get(REALM_ACCESS_ROLE); - - return roles.stream() - .map(role -> switch (role) { - case String r when r.equals(roleProperties.local_user()) -> - new SimpleGrantedAuthority(AuthConstants.generateAuthority(AuthorityRoleEnum.LOCAL_USER)); - case String r when r.equals(roleProperties.national_user()) -> - new SimpleGrantedAuthority(AuthConstants.generateAuthority(AuthorityRoleEnum.NATIONAL_USER)); - case String r when r.equals(roleProperties.interviewer()) -> - new SimpleGrantedAuthority(AuthConstants.generateAuthority(AuthorityRoleEnum.INTERVIEWER)); - case String r when r.equals(roleProperties.admin()) -> - new SimpleGrantedAuthority(AuthConstants.generateAuthority(AuthorityRoleEnum.ADMIN)); - case String r when r.equals(roleProperties.webclient()) -> - new SimpleGrantedAuthority(AuthConstants.generateAuthority(AuthorityRoleEnum.WEBCLIENT)); - default -> null; - }) - .filter(Objects::nonNull) - .collect(Collectors.toCollection(ArrayList::new)); - } -} \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/api/configuration/auth/KeycloakSecurityConfiguration.java b/src/main/java/fr/insee/pearljam/api/configuration/auth/KeycloakSecurityConfiguration.java deleted file mode 100644 index 475b1cdf..00000000 --- a/src/main/java/fr/insee/pearljam/api/configuration/auth/KeycloakSecurityConfiguration.java +++ /dev/null @@ -1,286 +0,0 @@ -package fr.insee.pearljam.api.configuration.auth; - -import java.util.Collection; - -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; -import org.springframework.core.convert.converter.Converter; -import org.springframework.http.HttpMethod; -import org.springframework.security.config.Customizer; -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.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.core.GrantedAuthority; -import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter; -import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter; - -import fr.insee.pearljam.api.configuration.properties.ApplicationProperties; -import fr.insee.pearljam.api.configuration.properties.AuthEnumProperties; -import fr.insee.pearljam.api.configuration.properties.KeycloakProperties; -import fr.insee.pearljam.api.configuration.properties.RoleProperties; -import fr.insee.pearljam.api.constants.Constants; -import lombok.RequiredArgsConstructor; - -/** - * This class defines the KeyCloak configuration - * - * @author scorcaud - * - */ -@Configuration -@ConditionalOnProperty(name = "application.auth", havingValue = "KEYCLOAK") -@EnableWebSecurity -@EnableMethodSecurity -@RequiredArgsConstructor -public class KeycloakSecurityConfiguration { - private final PublicSecurityFilterChain publicSecurityFilterChainConfiguration; - - /** - * Configure spring security filter chain to handle keycloak authentication - * AuthConstants.generateAuthority(AuthorityRoleEnum.LOCAL_USER) - * - * @param http Http Security Object - * @return the spring security filter - * @throws Exception exception - */ - @Bean - @Order(2) - protected SecurityFilterChain filterChain(HttpSecurity http, - RoleProperties roleProperties) throws Exception { - final String ADMIN = AuthConstants.generateAuthority(AuthorityRoleEnum.ADMIN); - final String LOCAL_USER = AuthConstants.generateAuthority(AuthorityRoleEnum.LOCAL_USER); - final String NATIONAL_USER = AuthConstants.generateAuthority(AuthorityRoleEnum.NATIONAL_USER); - final String INTERVIEWER = AuthConstants.generateAuthority(AuthorityRoleEnum.INTERVIEWER); - return http - .securityMatcher("/**") - .csrf(AbstractHttpConfigurer::disable) - .cors(Customizer.withDefaults()) - .headers(headers -> headers - .xssProtection(xssConfig -> xssConfig.headerValue( - XXssProtectionHeaderWriter.HeaderValue.DISABLED)) - .contentSecurityPolicy(cspConfig -> cspConfig.policyDirectives("default-src 'none'")) - .referrerPolicy(referrerPolicy -> referrerPolicy.policy( - ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN))) - .authorizeHttpRequests(configurer -> configurer - .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() - .requestMatchers(HttpMethod.GET, "/api/healthcheck").permitAll() - .requestMatchers(HttpMethod.GET, "/swagger-ui.html/**", "/v2/api-docs", "/csrf", "/", - "/webjars/**", "/swagger-resources/**") - .permitAll() - .requestMatchers(HttpMethod.GET, "/environnement", "/healthcheck").permitAll() - // configuration for endpoints - .requestMatchers(HttpMethod.GET, Constants.API_SURVEYUNITS) - .hasAnyAuthority(ADMIN, INTERVIEWER, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_SURVEYUNITS_TEMP_ZONE) - .hasAnyAuthority(ADMIN, INTERVIEWER, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.POST, - Constants.API_SURVEYUNITS) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.POST, - Constants.API_SURVEYUNITS_INTERVIEWERS) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.GET, Constants.API_SURVEYUNITS_CLOSABLE) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, - Constants.API_SURVEYUNIT_ID) - .hasAnyAuthority(ADMIN, INTERVIEWER) - .requestMatchers(HttpMethod.PUT, - Constants.API_SURVEYUNIT_ID) - .hasAnyAuthority(ADMIN, INTERVIEWER) - .requestMatchers(HttpMethod.POST, Constants.API_SURVEYUNIT_ID_TEMP_ZONE) - .hasAnyAuthority(ADMIN, INTERVIEWER) - .requestMatchers(HttpMethod.DELETE, - Constants.API_SURVEYUNIT_ID) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.PUT, Constants.API_SURVEYUNIT_ID_STATE) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_SURVEYUNIT_ID_STATES) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.PUT, Constants.API_SURVEYUNIT_ID_COMMENT) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.PUT, Constants.API_SURVEYUNIT_ID_VIEWED) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.PUT, Constants.API_SURVEYUNIT_ID_CLOSE) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.PUT, Constants.API_SURVEYUNIT_ID_CLOSINGCAUSE) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, - Constants.API_ADMIN_CAMPAIGNS) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGNS) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, - Constants.API_INTERVIEWER_CAMPAIGNS) - .hasAnyAuthority(INTERVIEWER) - .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGNS_SU_STATECOUNT) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGNS_SU_CONTACTOUTCOMES) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.POST, Constants.API_CAMPAIGN).hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.DELETE, - Constants.API_CAMPAIGN_ID) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.PUT, Constants.API_CAMPAIGN_ID).hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID) - .hasAnyAuthority(ADMIN, INTERVIEWER, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.PUT, Constants.API_CAMPAIGN_COLLECTION_DATES) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_INTERVIEWERS) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SURVEYUNITS) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_ABANDONED) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_NOTATTRIBUTED) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_STATECOUNT) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, - Constants.API_CAMPAIGN_ID_SU_INTERVIEWER_STATECOUNT) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, - Constants.API_CAMPAIGN_ID_SU_NOT_ATTRIBUTED_STATECOUNT) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_CONTACTOUTCOMES) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, - Constants.API_CAMPAIGN_ID_SU_INTERVIEWER_CONTACTOUTCOMES) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, - Constants.API_CAMPAIGN_ID_SU_NOT_ATTRIBUTED_CONTACTOUTCOMES) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, - Constants.API_CAMPAIGN_ID_SU_INTERVIEWER_CLOSINGCAUSES) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.PUT, Constants.API_CAMPAIGN_ID_OU_ID_VISIBILITY) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, - Constants.API_CAMPAIGN_ID_VISIBILITIES) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_REFERENTS) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, - Constants.API_CAMPAIGNS_ID_ON_GOING) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.GET, Constants.API_INTERVIEWERS) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.POST, - Constants.API_INTERVIEWERS) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.GET, - Constants.API_ADMIN_INTERVIEWERS) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.PUT, - Constants.API_INTERVIEWER_ID) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.DELETE, - Constants.API_INTERVIEWER_ID) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.GET, - Constants.API_INTERVIEWER_ID) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.GET, Constants.API_INTERVIEWERS_SU_STATECOUNT) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_INTERVIEWER_ID_CAMPAIGNS) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_USER).hasAnyAuthority(ADMIN, - LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.POST, Constants.API_USER).hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.GET, Constants.API_USER_ID).hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.PUT, Constants.API_USER_ID).hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.DELETE, Constants.API_USER_ID).hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.PUT, - Constants.API_USER_ID_ORGANIZATIONUNIT_ID) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.POST, - Constants.API_ORGANIZATIONUNIT) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.POST, - Constants.API_ORGANIZATIONUNITS) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.GET, - Constants.API_ORGANIZATIONUNITS) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.DELETE, - Constants.API_ORGANIZATIONUNIT_ID) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.POST, - Constants.API_ORGANIZATIONUNIT_ID_USERS) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.PUT, Constants.API_PREFERENCES) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.POST, Constants.API_MESSAGE) - .hasAnyAuthority(ADMIN, INTERVIEWER, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_MESSAGES_ID) - .hasAnyAuthority(ADMIN, INTERVIEWER, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.POST, Constants.API_VERIFYNAME) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.GET, Constants.API_MESSAGEHISTORY) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.PUT, Constants.API_MESSAGE_MARK_AS_READ) - .hasAnyAuthority(ADMIN, INTERVIEWER, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.PUT, Constants.API_MESSAGE_MARK_AS_DELETED) - .hasAnyAuthority(ADMIN, INTERVIEWER, LOCAL_USER, NATIONAL_USER) - .requestMatchers(HttpMethod.POST, - Constants.API_CREATEDATASET) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.DELETE, - Constants.API_DELETEDATASET) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.GET, Constants.API_CHECK_HABILITATION) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER, INTERVIEWER) - .requestMatchers(HttpMethod.POST, Constants.API_MAIL).hasAnyAuthority(ADMIN, - INTERVIEWER) - .requestMatchers(HttpMethod.GET, Constants.API_ENUM_STATE) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER, INTERVIEWER) - .requestMatchers(HttpMethod.GET, Constants.API_ENUM_CONTACT_ATTEMPT) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER, INTERVIEWER) - .requestMatchers(HttpMethod.GET, Constants.API_ENUM_CONTACT_OUTCOME) - .hasAnyAuthority(ADMIN, LOCAL_USER, NATIONAL_USER, INTERVIEWER) - .requestMatchers(HttpMethod.GET, - Constants.API_ADMIN_SURVEYUNITS) - .hasAnyAuthority(ADMIN) - .requestMatchers(HttpMethod.GET, - Constants.API_ADMIN_CAMPAIGN_ID_SURVEYUNITS) - .hasAnyAuthority(ADMIN) - // other requests should be rejected - .anyRequest().denyAll()) - - .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .oauth2ResourceServer(oauth2 -> oauth2 - .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter(roleProperties)))) - .build(); - } - - @Bean - @Order(1) - protected SecurityFilterChain filterPublicUrlsChain(HttpSecurity http, ApplicationProperties applicationProperties, - KeycloakProperties keycloakProperties) throws Exception { - String authorizedConnectionHost = applicationProperties.auth().equals(AuthEnumProperties.KEYCLOAK) - ? " " + keycloakProperties.authServerHost() - : ""; - return publicSecurityFilterChainConfiguration.buildSecurityPublicFilterChain(http, - applicationProperties.publicUrls(), authorizedConnectionHost); - } - - @Bean - protected JwtAuthenticationConverter jwtAuthenticationConverter(RoleProperties roleProperties) { - JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); - jwtAuthenticationConverter.setPrincipalClaimName("name"); - jwtAuthenticationConverter - .setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter(roleProperties)); - return jwtAuthenticationConverter; - } - - Converter> jwtGrantedAuthoritiesConverter(RoleProperties roleProperties) { - return new GrantedAuthorityConverter(roleProperties); - } - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/api/configuration/auth/NoAuthSecurityConfiguration.java b/src/main/java/fr/insee/pearljam/api/configuration/auth/NoAuthSecurityConfiguration.java deleted file mode 100644 index a20b56be..00000000 --- a/src/main/java/fr/insee/pearljam/api/configuration/auth/NoAuthSecurityConfiguration.java +++ /dev/null @@ -1,80 +0,0 @@ -package fr.insee.pearljam.api.configuration.auth; - -import fr.insee.pearljam.api.configuration.properties.ApplicationProperties; -import lombok.AllArgsConstructor; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.core.annotation.Order; -import org.springframework.security.config.Customizer; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; -import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter; -import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter; -import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter; -import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter.XFrameOptionsMode; -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; - -import static org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher; - -@ConditionalOnProperty(name = "application.auth", havingValue = "NOAUTH") -@Configuration -@EnableWebSecurity -@AllArgsConstructor -public class NoAuthSecurityConfiguration { - private final PublicSecurityFilterChain publicSecurityFilterChainConfiguration; - - /** - * Configure spring security filter chain when no authentication - * - * @param http Http Security Object - * @return the spring security filter - * @throws Exception exception - */ - @Bean - @Order(2) - protected SecurityFilterChain filterChain(HttpSecurity http, HandlerMappingIntrospector introspector) - throws Exception { - MvcRequestMatcher.Builder mvcMatcherBuilder = new MvcRequestMatcher.Builder(introspector); - - return http - .securityMatcher("/**") - .csrf(AbstractHttpConfigurer::disable) - .cors(Customizer.withDefaults()) - .headers(headers -> headers - .xssProtection(xssConfig -> xssConfig.headerValue( - XXssProtectionHeaderWriter.HeaderValue.DISABLED)) - .contentSecurityPolicy(cspConfig -> cspConfig - .policyDirectives("default-src 'self' ; " + - "connect-src 'self' ; " + - "img-src 'self' data:; " + - "style-src 'self' ; " + - "script-src 'self' 'unsafe-inline'")) - .referrerPolicy(referrerPolicy -> referrerPolicy - .policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN)) - .addHeaderWriter(new XFrameOptionsHeaderWriter( - XFrameOptionsMode.SAMEORIGIN))) - - .anonymous(anonymousConfig -> anonymousConfig - .authorities(AuthConstants.ROLE_PREFIX + AuthorityRoleEnum.ADMIN)) - .authorizeHttpRequests( - authorize -> authorize - .requestMatchers(mvcMatcherBuilder.pattern("/api/**")) - .permitAll() - .requestMatchers(antMatcher("/h2-console/**")) - .permitAll()) - .build(); - } - - @Bean - @Order(1) - protected SecurityFilterChain filterPublicUrlsChain(HttpSecurity http, - ApplicationProperties applicationProperties, MvcRequestMatcher.Builder mvc) throws Exception { - return publicSecurityFilterChainConfiguration.buildSecurityPublicFilterChain(http, - applicationProperties.publicUrls()); - } - -} \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/api/configuration/auth/PublicSecurityFilterChain.java b/src/main/java/fr/insee/pearljam/api/configuration/auth/PublicSecurityFilterChain.java deleted file mode 100644 index 25ea6983..00000000 --- a/src/main/java/fr/insee/pearljam/api/configuration/auth/PublicSecurityFilterChain.java +++ /dev/null @@ -1,72 +0,0 @@ -package fr.insee.pearljam.api.configuration.auth; - -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.security.config.Customizer; -import org.springframework.security.config.annotation.web.builders.HttpSecurity; -import org.springframework.security.config.http.SessionCreationPolicy; -import org.springframework.security.web.SecurityFilterChain; -import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter; -import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter; -import org.springframework.security.web.servlet.util.matcher.MvcRequestMatcher; -import org.springframework.security.web.util.matcher.AntPathRequestMatcher; -import org.springframework.web.servlet.handler.HandlerMappingIntrospector; - -@Configuration -public class PublicSecurityFilterChain { - - private static final String H2_CONSOLE_PATH = "/h2-console/**"; - private final MvcRequestMatcher.Builder mvc; - - public PublicSecurityFilterChain(HandlerMappingIntrospector introspector) { - this.mvc = new MvcRequestMatcher.Builder(introspector); - } - - @Bean - MvcRequestMatcher.Builder mvc(HandlerMappingIntrospector introspector) { - return new MvcRequestMatcher.Builder(introspector); - } - - SecurityFilterChain buildSecurityPublicFilterChain(HttpSecurity http, - String[] publicUrls) throws Exception { - return buildSecurityPublicFilterChain(http, mvc, publicUrls, H2_CONSOLE_PATH); - } - - SecurityFilterChain buildSecurityPublicFilterChain(HttpSecurity http, - String[] publicUrls, String authorizedConnectionHost) throws Exception { - return buildSecurityPublicFilterChain(http, mvc, publicUrls, authorizedConnectionHost); - } - - SecurityFilterChain buildSecurityPublicFilterChain(HttpSecurity http, MvcRequestMatcher.Builder mvc, - String[] publicUrls, - String authorizedConnectionHost) throws Exception { - return http - .securityMatcher(publicUrls) - .csrf(csrf -> csrf - .ignoringRequestMatchers( - AntPathRequestMatcher.antMatcher(H2_CONSOLE_PATH))) - .cors(Customizer.withDefaults()) - .headers(headers -> headers - .xssProtection(xssConfig -> xssConfig.headerValue( - XXssProtectionHeaderWriter.HeaderValue.DISABLED)) - .contentSecurityPolicy(cspConfig -> cspConfig - .policyDirectives("default-src 'none' ; " + - "connect-src 'self' ; " + - "img-src 'self' data:; " + - "style-src 'self' " - + authorizedConnectionHost + " ; " + - "script-src 'self' 'unsafe-inline'")) - .referrerPolicy(referrerPolicy -> referrerPolicy - .policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN))) - - .authorizeHttpRequests(auth -> auth - // .requestMatchers(HttpMethod.OPTIONS).permitAll() - .requestMatchers(new AntPathRequestMatcher(H2_CONSOLE_PATH)) - .permitAll() - .requestMatchers(mvc.pattern("/**")).permitAll() - .anyRequest() - .authenticated()) - .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) - .build(); - } -} diff --git a/src/main/java/fr/insee/pearljam/api/configuration/log/LogInterceptor.java b/src/main/java/fr/insee/pearljam/api/configuration/log/LogInterceptor.java index 55e528e2..edf73435 100644 --- a/src/main/java/fr/insee/pearljam/api/configuration/log/LogInterceptor.java +++ b/src/main/java/fr/insee/pearljam/api/configuration/log/LogInterceptor.java @@ -1,6 +1,6 @@ package fr.insee.pearljam.api.configuration.log; -import fr.insee.pearljam.api.web.authentication.AuthenticationHelper; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; @@ -8,7 +8,6 @@ import org.slf4j.MDC; import org.springframework.lang.NonNull; import org.springframework.lang.Nullable; -import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; @@ -19,7 +18,7 @@ @RequiredArgsConstructor @Slf4j public class LogInterceptor implements HandlerInterceptor { - private final AuthenticationHelper authenticationHelper; + private final AuthenticatedUserService authenticationUserHelper; @Override public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServletResponse response, @@ -28,9 +27,7 @@ public boolean preHandle(@NonNull HttpServletRequest request, @NonNull HttpServl String method = request.getMethod(); String operationPath = request.getRequestURI(); - Authentication authentication = authenticationHelper.getAuthenticationPrincipal(); - - String userId = authentication.getName(); + String userId = authenticationUserHelper.getCurrentUserId(); MDC.put("id", fishTag); MDC.put("path", operationPath); diff --git a/src/main/java/fr/insee/pearljam/api/PropertiesLogger.java b/src/main/java/fr/insee/pearljam/api/configuration/log/PropertiesLogger.java similarity index 68% rename from src/main/java/fr/insee/pearljam/api/PropertiesLogger.java rename to src/main/java/fr/insee/pearljam/api/configuration/log/PropertiesLogger.java index 2c122466..569b5b14 100644 --- a/src/main/java/fr/insee/pearljam/api/PropertiesLogger.java +++ b/src/main/java/fr/insee/pearljam/api/configuration/log/PropertiesLogger.java @@ -1,4 +1,4 @@ -package fr.insee.pearljam.api; +package fr.insee.pearljam.api.configuration.log; import lombok.NonNull; import lombok.extern.slf4j.Slf4j; @@ -9,13 +9,14 @@ import org.springframework.core.env.Environment; import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.Set; @Slf4j public class PropertiesLogger implements ApplicationListener { - private static final Set hiddenWords = Set.of("password", "pwd", "jeton", "token", "secret", "credentials"); + private static final Set hiddenWords = Set.of("password", "pwd", "jeton", "token", "secret"); @Override public void onApplicationEvent(@NonNull ApplicationEnvironmentPreparedEvent event) { @@ -24,12 +25,23 @@ public void onApplicationEvent(@NonNull ApplicationEnvironmentPreparedEvent even log.info("==============================================================================================="); log.info(" Properties "); + List propertyObjects = List.of("fr.insee", "application", "spring", "feature", "logging"); ((AbstractEnvironment) environment).getPropertySources().stream() .filter(EnumerablePropertySource.class::isInstance) - .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()).flatMap(Arrays::stream).distinct() + .map(ps -> ((EnumerablePropertySource) ps).getPropertyNames()) + .flatMap(Arrays::stream) + .distinct() .filter(Objects::nonNull) - .filter(ps -> ps.startsWith("fr.insee") || ps.startsWith("spring")).forEach(key -> log - .info("{} = {}", key, hideProperties(key, environment))); + .sorted() + .filter(ps -> { + for(String propertyObject : propertyObjects) { + if(ps.startsWith(propertyObject)) { + return true; + } + } + return false; + }) + .forEach(key -> log.info("{} = {}", key, hideProperties(key, environment))); log.info("==============================================================================================="); } @@ -41,4 +53,4 @@ private static Object hideProperties(String key, Environment environment) { return environment.getProperty(key); } -} \ No newline at end of file +} diff --git a/src/main/java/fr/insee/pearljam/api/configuration/properties/ApplicationProperties.java b/src/main/java/fr/insee/pearljam/api/configuration/properties/ApplicationProperties.java index a0cdd69c..a92df7dd 100644 --- a/src/main/java/fr/insee/pearljam/api/configuration/properties/ApplicationProperties.java +++ b/src/main/java/fr/insee/pearljam/api/configuration/properties/ApplicationProperties.java @@ -2,50 +2,12 @@ import org.springframework.boot.context.properties.ConfigurationProperties; -import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.NotEmpty; - -import java.util.Arrays; import java.util.List; -import java.util.Objects; @ConfigurationProperties(prefix = "application") public record ApplicationProperties( String host, - String[] publicUrls, @NotEmpty(message = "cors origins must be specified (application.corsOrigins)") List corsOrigins, - @NotEmpty(message = "Folder where temp files will be created cannot be empty.") String tempFolder, - @NotNull(message = "application.auth must be specified (KEYCLOAK or NOAUTH)") AuthEnumProperties auth, - String guestOU) { - - @Override - public boolean equals(Object o) { - if (this == o) - return true; - if (o == null || getClass() != o.getClass()) - return false; - ApplicationProperties that = (ApplicationProperties) o; - return Objects.equals(host, that.host) - && Arrays.equals(publicUrls, that.publicUrls) - && Objects.equals(guestOU, that.guestOU) - && auth.equals(that.auth); - } - - @Override - public int hashCode() { - int result = Objects.hash(host, guestOU, auth); - result = 31 * result + Arrays.hashCode(publicUrls); - return result; - } - - @Override - public String toString() { - return "ApplicationProperties{" + - "host='" + host + '\'' + - ", guestOU='" + guestOU + '\'' + - ", publicUrls=" + Arrays.toString(publicUrls) + - ", auth='" + auth + '\'' + - '}'; - } - + @NotEmpty(message = "Folder where temp files will be created cannot be empty.") String tempFolder) { } \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/api/controller/CampaignController.java b/src/main/java/fr/insee/pearljam/api/controller/CampaignController.java index 5da80031..d5666e2d 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/CampaignController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/CampaignController.java @@ -3,10 +3,10 @@ import java.util.List; import java.util.Optional; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -34,7 +34,6 @@ import fr.insee.pearljam.api.exception.VisibilityException; import fr.insee.pearljam.api.service.CampaignService; import fr.insee.pearljam.api.service.ReferentService; -import fr.insee.pearljam.api.web.authentication.AuthenticationHelper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -48,8 +47,8 @@ public class CampaignController { private final CampaignService campaignService; - private final AuthenticationHelper authHelper; private final ReferentService referentService; + private final AuthenticatedUserService authenticatedUserService; private static final String NO_USER_ID = "No userId : access denied."; private static final String DEFAULT_FORCE_VALUE = "false"; @@ -62,10 +61,9 @@ public class CampaignController { */ @Operation(summary = "Post Campaign") @PostMapping(path = Constants.API_CAMPAIGN) - public ResponseEntity postCampaign(Authentication auth, - @RequestBody CampaignContextDto campaignDto) { + public ResponseEntity postCampaign(@RequestBody CampaignContextDto campaignDto) { + String userId = authenticatedUserService.getCurrentUserId(); Response response; - String userId = authHelper.getUserId(auth); try { response = campaignService.postCampaign(campaignDto); } catch (NoOrganizationUnitException | VisibilityException e) { @@ -86,8 +84,8 @@ public ResponseEntity postCampaign(Authentication auth, */ @Operation(summary = "Get user related Campaigns") @GetMapping(path = Constants.API_CAMPAIGNS) - public ResponseEntity> getListCampaign(Authentication auth) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getListCampaign() { + String userId = authenticatedUserService.getCurrentUserId(); log.info("User {} : GET related campaigns", userId); if (StringUtils.isBlank(userId)) { log.warn(NO_USER_ID); @@ -108,8 +106,8 @@ public ResponseEntity> getListCampaign(Authentication auth) { */ @Operation(summary = "Get Campaigns") @GetMapping(path = Constants.API_ADMIN_CAMPAIGNS) - public ResponseEntity> getAllCampaigns(Authentication auth) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getAllCampaigns() { + String userId = authenticatedUserService.getCurrentUserId(); log.info("User {} : GET all campaigns", userId); if (StringUtils.isBlank(userId)) { log.warn(NO_USER_ID); @@ -131,8 +129,8 @@ public ResponseEntity> getAllCampaigns(Authentication auth) { */ @Operation(summary = "Get interviewer related Campaigns") @GetMapping(path = Constants.API_INTERVIEWER_CAMPAIGNS) - public ResponseEntity> getInterviewerCampaigns(Authentication auth) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getInterviewerCampaigns() { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { log.warn(NO_USER_ID); return new ResponseEntity<>(HttpStatus.FORBIDDEN); @@ -155,9 +153,8 @@ public ResponseEntity> getInterviewerCampaigns(Authentication */ @Operation(summary = "Get interviewers") @GetMapping(path = Constants.API_CAMPAIGN_ID_INTERVIEWERS) - public ResponseEntity> getListInterviewers(Authentication auth, - @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getListInterviewers(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { log.warn(NO_USER_ID); return new ResponseEntity<>(HttpStatus.FORBIDDEN); @@ -189,9 +186,8 @@ public ResponseEntity> getListInterviewers(Authentication a */ @Operation(summary = "Get campaign visibilities") @GetMapping(path = Constants.API_CAMPAIGN_ID_VISIBILITIES) - public ResponseEntity> getVisibilities(Authentication auth, - @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getVisibilities(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { log.warn(NO_USER_ID); return new ResponseEntity<>(HttpStatus.FORBIDDEN); @@ -221,9 +217,8 @@ public ResponseEntity> getVisibilities(Authentication */ @Operation(summary = "Get numberSUAbandoned") @GetMapping(path = Constants.API_CAMPAIGN_ID_SU_ABANDONED) - public ResponseEntity getNbSUAbandoned(Authentication auth, - @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity getNbSUAbandoned(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { log.warn(NO_USER_ID); return new ResponseEntity<>(HttpStatus.FORBIDDEN); @@ -252,17 +247,16 @@ public ResponseEntity getNbSUAbandoned(Authentication auth, */ @Operation(summary = "Get numberSUNotAttributed") @GetMapping(path = Constants.API_CAMPAIGN_ID_SU_NOTATTRIBUTED) - public ResponseEntity getNbSUNotAttributed(Authentication auth, - @PathVariable(value = "id") String id) { - String callerId = authHelper.getUserId(auth); - if (StringUtils.isBlank(callerId)) { + public ResponseEntity getNbSUNotAttributed(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); + if (StringUtils.isBlank(userId)) { log.warn(NO_USER_ID); return new ResponseEntity<>(HttpStatus.FORBIDDEN); } - log.info("{} try to get campaign[{}] not attributed survey-units ", callerId, id); + log.info("{} try to get campaign[{}] not attributed survey-units ", userId, id); CountDto nbSUNotAttributed; try { - nbSUNotAttributed = campaignService.getNbSUNotAttributedByCampaign(callerId, id); + nbSUNotAttributed = campaignService.getNbSUNotAttributedByCampaign(userId, id); } catch (NotFoundException e) { log.info("Get numberSUAbandoned resulting in 404"); return new ResponseEntity<>(HttpStatus.NOT_FOUND); @@ -281,15 +275,16 @@ public ResponseEntity getNbSUNotAttributed(Authentication auth, */ @Operation(summary = "Change visibility of a campaign for an Organizational Unit") @PutMapping(path = Constants.API_CAMPAIGN_ID_OU_ID_VISIBILITY) - public ResponseEntity putVisibilityDate(Authentication auth, - @RequestBody VisibilityDto visibilityUpdated, @PathVariable(value = "idCampaign") String idCampaign, + public ResponseEntity putVisibilityDate( + @RequestBody VisibilityDto visibilityUpdated, + @PathVariable(value = "idCampaign") String idCampaign, @PathVariable(value = "idOu") String idOu) { - String callerId = authHelper.getUserId(auth); - if (StringUtils.isBlank(callerId)) { + String userId = authenticatedUserService.getCurrentUserId(); + if (StringUtils.isBlank(userId)) { log.info(NO_USER_ID); return new ResponseEntity<>(NO_USER_ID, HttpStatus.FORBIDDEN); } - log.info("{} try to change OU[{}] visibility on campaign[{}] ", callerId, idOu, idCampaign); + log.info("{} try to change OU[{}] visibility on campaign[{}] ", userId, idOu, idCampaign); HttpStatus returnCode = campaignService.updateVisibility(idCampaign, idOu, visibilityUpdated); log.info("PUT visibility with CampaignId {} for Organizational Unit {} resulting in {}", idCampaign, idOu, returnCode.value()); @@ -306,10 +301,11 @@ public ResponseEntity putVisibilityDate(Authentication auth, */ @Operation(summary = "Delete a campaign") @DeleteMapping(path = Constants.API_CAMPAIGN_ID) - public ResponseEntity deleteCampaignById(Authentication auth, @PathVariable(value = "id") String id, + public ResponseEntity deleteCampaignById( + @PathVariable(value = "id") String id, @RequestParam(required = false, defaultValue = DEFAULT_FORCE_VALUE) Boolean force) { - String callerId = authHelper.getUserId(auth); - log.info("{} try to delete campaign {}", callerId, id); + String userId = authenticatedUserService.getCurrentUserId(); + log.info("{} try to delete campaign {}", userId, id); Optional campaignOptional = campaignService.findById(id); if (!campaignOptional.isPresent()) { @@ -336,12 +332,12 @@ public ResponseEntity deleteCampaignById(Authentication auth, @PathVaria */ @Operation(summary = "Update campaign (label, email, configurations, visibilities") @PutMapping(path = Constants.API_CAMPAIGN_ID) - public ResponseEntity putCampaign(Authentication auth, - @PathVariable(value = "id") String id, @RequestBody CampaignContextDto campaign) { - String callerId = authHelper.getUserId(auth); - log.info("{} try to update campaign {} collection dates", callerId, id); + public ResponseEntity putCampaign(@PathVariable(value = "id") String id, + @RequestBody CampaignContextDto campaign) { + String userId = authenticatedUserService.getCurrentUserId(); + log.info("{} try to update campaign {} collection dates", userId, id); - if (StringUtils.isBlank(callerId)) { + if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } HttpStatus returnCode = campaignService.updateCampaign(id, campaign); @@ -360,10 +356,9 @@ public ResponseEntity putCampaign(Authentication auth, */ @Operation(summary = "Check if campaign is on-going") @GetMapping(path = Constants.API_CAMPAIGNS_ID_ON_GOING) - public ResponseEntity isOngoing(Authentication auth, - @PathVariable(value = "id") String id) { - String callerId = authHelper.getUserId(auth); - log.info("{} check if {} is on-going", callerId, id); + public ResponseEntity isOngoing(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); + log.info("{} check if {} is on-going", userId, id); if (!campaignService.findById(id).isPresent()) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); @@ -372,7 +367,7 @@ public ResponseEntity isOngoing(Authentication auth, OngoingDto campaignOngoing = new OngoingDto(); campaignOngoing.setOngoing(campaignService.isCampaignOngoing(id)); - log.info("{} checked if campaign {} is on-going : {}", callerId, id, campaignOngoing.isOngoing()); + log.info("{} checked if campaign {} is on-going : {}", userId, id, campaignOngoing.isOngoing()); return new ResponseEntity<>(campaignOngoing, HttpStatus.OK); } @@ -386,10 +381,9 @@ public ResponseEntity isOngoing(Authentication auth, */ @Operation(summary = "Get target campaign") @GetMapping(path = Constants.API_CAMPAIGN_ID) - public ResponseEntity getCampaign(Authentication auth, - @PathVariable(value = "id") String id) { - String callerId = authHelper.getUserId(auth); - log.info("{} try to GET {}", callerId, id); + public ResponseEntity getCampaign(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); + log.info("{} try to GET {}", userId, id); if (!campaignService.findById(id).isPresent()) { return new ResponseEntity<>(HttpStatus.NOT_FOUND); @@ -397,7 +391,7 @@ public ResponseEntity getCampaign(Authentication auth, CampaignContextDto campaign = campaignService.getCampaignDtoById(id); - log.info("{} GET campaign {} : {}", callerId, id, HttpStatus.OK.toString()); + log.info("{} GET campaign {} : {}", userId, id, HttpStatus.OK.toString()); return new ResponseEntity<>(campaign, HttpStatus.OK); } @@ -405,10 +399,9 @@ public ResponseEntity getCampaign(Authentication auth, @Operation(summary = "Get referents of targeted campaign") @GetMapping(path = Constants.API_CAMPAIGN_ID_REFERENTS) - public ResponseEntity> getReferents(Authentication auth, - @PathVariable(value = "id") String id) { - String callerId = authHelper.getUserId(auth); - log.info("{} try to GET {} referents", callerId, id); + public ResponseEntity> getReferents(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); + log.info("{} try to GET {} referents", userId, id); if (!campaignService.findById(id).isPresent()) { log.warn("Campaign {} is not present, can't get referents", id); return new ResponseEntity<>(HttpStatus.NOT_FOUND); @@ -416,7 +409,7 @@ public ResponseEntity> getReferents(Authentication auth, List referents = referentService.findByCampaignId(id); - log.info("{} GOT {} referents for campaign {}", callerId, referents.size(), id); + log.info("{} GOT {} referents for campaign {}", userId, referents.size(), id); return new ResponseEntity<>(referents, HttpStatus.OK); } diff --git a/src/main/java/fr/insee/pearljam/api/controller/ClosingCauseController.java b/src/main/java/fr/insee/pearljam/api/controller/ClosingCauseController.java index 39269dbb..730b73d8 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/ClosingCauseController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/ClosingCauseController.java @@ -2,22 +2,20 @@ import java.util.List; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; - import fr.insee.pearljam.api.dto.closingcause.ClosingCauseCountDto; import fr.insee.pearljam.api.dto.state.StateCountDto; import fr.insee.pearljam.api.exception.NotFoundException; import fr.insee.pearljam.api.service.ClosingCauseService; import fr.insee.pearljam.api.service.UtilsService; -import fr.insee.pearljam.api.web.authentication.AuthenticationHelper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -30,9 +28,9 @@ @RequiredArgsConstructor public class ClosingCauseController { - private final AuthenticationHelper authHelper; private final ClosingCauseService closingCauseService; private final UtilsService utilsService; + private final AuthenticatedUserService authenticatedUserService; /** * This method is used to count survey units by states, interviewer and campaign @@ -46,18 +44,18 @@ public class ClosingCauseController { */ @Operation(summary = "Get interviewerStateCount") @GetMapping(path = "/campaign/{id}/survey-units/interviewer/{idep}/closing-causes") - public ResponseEntity getClosingCauseCount(Authentication auth, + public ResponseEntity getClosingCauseCount( @PathVariable(value = "id") String id, @PathVariable(value = "idep") String idep, @RequestParam(required = false, name = "date") Long date) { - String callerId = authHelper.getUserId(auth); - List associatedOrgUnits = utilsService.getRelatedOrganizationUnits(callerId); + String userId = authenticatedUserService.getCurrentUserId(); + List associatedOrgUnits = utilsService.getRelatedOrganizationUnits(userId); - if (StringUtils.isBlank(callerId)) { + if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { ClosingCauseCountDto closingCountDto; try { - closingCountDto = closingCauseService.getClosingCauseCount(callerId, id, idep, date, + closingCountDto = closingCauseService.getClosingCauseCount(userId, id, idep, date, associatedOrgUnits); } catch (NotFoundException e) { log.error(e.getMessage()); diff --git a/src/main/java/fr/insee/pearljam/api/controller/ContactOutcomeController.java b/src/main/java/fr/insee/pearljam/api/controller/ContactOutcomeController.java index 8a9e0539..f33151c5 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/ContactOutcomeController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/ContactOutcomeController.java @@ -2,10 +2,10 @@ import java.util.List; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -19,7 +19,6 @@ import fr.insee.pearljam.api.dto.state.StateCountDto; import fr.insee.pearljam.api.exception.NotFoundException; import fr.insee.pearljam.api.service.ContactOutcomeService; -import fr.insee.pearljam.api.web.authentication.AuthenticationHelper; import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -31,7 +30,7 @@ public class ContactOutcomeController { private final ContactOutcomeService contactOutcomeService; - private final AuthenticationHelper authHelper; + private final AuthenticatedUserService authenticatedUserService; /** * This method is used to count survey units not attributed by contact-outcomes @@ -43,9 +42,9 @@ public class ContactOutcomeController { */ @Operation(summary = "Get Contact-outcomes count for non attributted SUs") @GetMapping(path = "/campaign/{id}/survey-units/not-attributed/contact-outcomes") - public ResponseEntity getNbSUNotAttributedContactOutcomes(Authentication auth, + public ResponseEntity getNbSUNotAttributedContactOutcomes( @PathVariable(value = "id") String id, @RequestParam(required = false, name = "date") Long date) { - String userId = authHelper.getUserId(auth); + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { @@ -74,9 +73,8 @@ public ResponseEntity getNbSUNotAttributedContactOut @Operation(summary = "Get campaignStateCount") @GetMapping(path = "/campaigns/survey-units/contact-outcomes") public ResponseEntity> getCampaignsContactOutcomeTypeCount( - Authentication auth, @RequestParam(required = false, name = "date") Long date) { - String userId = authHelper.getUserId(auth); + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { @@ -104,9 +102,8 @@ public ResponseEntity> getCampaignsContactOutco @Operation(summary = "Get campaignStateCount") @GetMapping(path = "/campaign/{id}/survey-units/contact-outcomes") public ResponseEntity getContactOutcomeTypeCountByCampaign( - Authentication auth, @PathVariable(value = "id") String id, @RequestParam(required = false, name = "date") Long date) { - String userId = authHelper.getUserId(auth); + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { @@ -135,10 +132,9 @@ public ResponseEntity getContactOutcomeTypeC @Operation(summary = "Get contact-outcome type for an interviewer on a specific campaign") @GetMapping(path = "/campaign/{id}/survey-units/interviewer/{idep}/contact-outcomes") public ResponseEntity getContactOuctomeByCampaignAndInterviewer( - Authentication auth, @PathVariable(value = "id") String id, @PathVariable(value = "idep") String idep, @RequestParam(required = false, name = "date") Long date) { - String userId = authHelper.getUserId(auth); + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } diff --git a/src/main/java/fr/insee/pearljam/api/controller/InterviewerController.java b/src/main/java/fr/insee/pearljam/api/controller/InterviewerController.java index c6742ffb..23a30b50 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/InterviewerController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/InterviewerController.java @@ -4,10 +4,10 @@ import java.util.Optional; import java.util.Set; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -23,7 +23,6 @@ import fr.insee.pearljam.api.dto.interviewer.InterviewerContextDto; import fr.insee.pearljam.api.dto.interviewer.InterviewerDto; import fr.insee.pearljam.api.service.InterviewerService; -import fr.insee.pearljam.api.web.authentication.AuthenticationHelper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -35,8 +34,8 @@ @RequiredArgsConstructor public class InterviewerController { - private final AuthenticationHelper authHelper; private final InterviewerService interviewerService; + private final AuthenticatedUserService authenticatedUserService; /** * This method is used to post the list of interviewers defined in request body @@ -48,9 +47,8 @@ public class InterviewerController { */ @Operation(summary = "Post interviewers") @PostMapping(path = Constants.API_INTERVIEWERS) - public ResponseEntity postInterviewers(Authentication auth, - @RequestBody List interviewers) { - String userId = authHelper.getUserId(auth); + public ResponseEntity postInterviewers(@RequestBody List interviewers) { + String userId = authenticatedUserService.getCurrentUserId(); Response response = interviewerService.createInterviewers(interviewers); log.info("{} : POST /interviewers resulting in {} with response [{}]", userId, response.getHttpStatus(), response.getMessage()); @@ -68,8 +66,8 @@ public ResponseEntity postInterviewers(Authentication auth, */ @Operation(summary = "Get interviewers") @GetMapping(path = Constants.API_INTERVIEWERS) - public ResponseEntity> getListInterviewers(Authentication auth) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getListInterviewers() { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -85,9 +83,8 @@ public ResponseEntity> getListInterviewers(Authentication au @Operation(summary = "Get interviewer by Id") @GetMapping(path = Constants.API_INTERVIEWER_ID) - public ResponseEntity getInterviewer(Authentication auth, - @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity getInterviewer(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { log.info("{} -> Get interviewer [{}] resulting in 403 : unknown user", userId, id); return new ResponseEntity<>(HttpStatus.FORBIDDEN); @@ -104,8 +101,8 @@ public ResponseEntity getInterviewer(Authentication auth, @Operation(summary = "Get all interviewers") @GetMapping(path = Constants.API_ADMIN_INTERVIEWERS) - public ResponseEntity> getCompleteListInterviewers(Authentication auth) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getCompleteListInterviewers() { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -121,9 +118,8 @@ public ResponseEntity> getCompleteListInterviewers(A @Operation(summary = "Get interviewer campaigns") @GetMapping(path = Constants.API_INTERVIEWER_ID_CAMPAIGNS) - public ResponseEntity> getListCampaigns(Authentication auth, - @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getListCampaigns(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -139,9 +135,10 @@ public ResponseEntity> getListCampaigns(Authentication auth, @Operation(summary = "Update interviewer") @PutMapping(path = Constants.API_INTERVIEWER_ID) - public ResponseEntity updateInterviewer(Authentication auth, - @PathVariable(value = "id") String id, @RequestBody InterviewerContextDto interviewer) { - String userId = authHelper.getUserId(auth); + public ResponseEntity updateInterviewer( + @PathVariable(value = "id") String id, + @RequestBody InterviewerContextDto interviewer) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) return new ResponseEntity<>(HttpStatus.FORBIDDEN); @@ -161,9 +158,8 @@ public ResponseEntity updateInterviewer(Authentication au @Operation(summary = "Delete interviewer") @DeleteMapping(path = Constants.API_INTERVIEWER_ID) - public ResponseEntity deleteInterviewer(Authentication auth, - @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity deleteInterviewer(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { log.warn("{} : DELETE interviewer with id {} resulting in 403.", userId, id); return new ResponseEntity<>(HttpStatus.FORBIDDEN); diff --git a/src/main/java/fr/insee/pearljam/api/controller/MessageController.java b/src/main/java/fr/insee/pearljam/api/controller/MessageController.java index 23a54530..578a9b5e 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/MessageController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/MessageController.java @@ -3,12 +3,12 @@ import java.util.List; import java.util.function.BiFunction; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.messaging.simp.SimpMessagingTemplate; import org.springframework.messaging.simp.stomp.StompSessionHandler; -import org.springframework.security.core.Authentication; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -17,13 +17,10 @@ import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; -import fr.insee.pearljam.api.constants.Constants; import fr.insee.pearljam.api.dto.message.MailDto; import fr.insee.pearljam.api.dto.message.MessageDto; import fr.insee.pearljam.api.dto.message.VerifyNameResponseDto; import fr.insee.pearljam.api.service.MessageService; -import fr.insee.pearljam.api.service.UtilsService; -import fr.insee.pearljam.api.web.authentication.AuthenticationHelper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -38,10 +35,9 @@ public class MessageController { private final MessageService messageService; private final BiFunction sendMail; - private final UtilsService utilsService; private final SimpMessagingTemplate brokerMessagingTemplate; - private final AuthenticationHelper authHelper; - + private final AuthenticatedUserService authenticatedUserService; + StompSessionHandler sessionHandler = new CustomStompSessionHandler(); /** @@ -49,15 +45,11 @@ public class MessageController { */ @Operation(summary = "Post a message") @PostMapping(path = "/message") - public ResponseEntity postMessage(Authentication auth, @RequestBody MessageDto message) { - String userId = authHelper.getUserId(auth); + public ResponseEntity postMessage(@RequestBody MessageDto message) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { - if (!userId.equals(Constants.GUEST) && utilsService.existUser(userId, Constants.USER) - && !userId.equalsIgnoreCase(message.getSender())) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } String text = message.getText(); List recipients = message.getRecipients(); log.info("POST text '{}' ", text); @@ -75,9 +67,10 @@ public ResponseEntity postMessage(Authentication auth, @RequestBody Mess */ @Operation(summary = "Mark a message as read") @PutMapping(path = "/message/{id}/interviewer/{idep}/read") - public ResponseEntity postMessage(Authentication auth, @PathVariable(value = "id") Long id, + public ResponseEntity postMessage( + @PathVariable(value = "id") Long id, @PathVariable(value = "idep") String idep) { - String userId = authHelper.getUserId(auth); + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { @@ -96,9 +89,10 @@ public ResponseEntity postMessage(Authentication auth, @PathVariable(val */ @Operation(summary = "Mark a message as deleted") @PutMapping(path = "/message/{id}/interviewer/{idep}/delete") - public ResponseEntity postDeletedMessage(Authentication auth, @PathVariable(value = "id") Long id, + public ResponseEntity postDeletedMessage( + @PathVariable(value = "id") Long id, @PathVariable(value = "idep") String idep) { - String userId = authHelper.getUserId(auth); + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { @@ -116,9 +110,8 @@ public ResponseEntity postDeletedMessage(Authentication auth, @PathVaria */ @Operation(summary = "Get a message") @GetMapping(path = "/messages/{id}") - public ResponseEntity> getMessages(Authentication auth, - @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getMessages(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { @@ -132,8 +125,8 @@ public ResponseEntity> getMessages(Authentication auth, */ @Operation(summary = "Get the message history") @GetMapping(path = "/message-history") - public ResponseEntity> getMessageHistory(Authentication auth) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getMessageHistory() { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { @@ -147,8 +140,8 @@ public ResponseEntity> getMessageHistory(Authentication auth) { */ @Operation(summary = "Update Messages with campaigns or interviewers listed in request body") @PostMapping(path = "/verify-name") - public ResponseEntity postMessage(Authentication auth, @RequestBody WsText name) { - String userId = authHelper.getUserId(auth); + public ResponseEntity postMessage(@RequestBody WsText name) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { @@ -166,8 +159,8 @@ public ResponseEntity postMessage(Authentication auth, @RequestBody WsTe */ @Operation(summary = "Post a mail to admins") @PostMapping(path = "/mail") - public ResponseEntity postMailMessage(Authentication auth, @RequestBody MailDto mail) { - String userId = authHelper.getUserId(auth); + public ResponseEntity postMailMessage(@RequestBody MailDto mail) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } diff --git a/src/main/java/fr/insee/pearljam/api/controller/OrganizationUnitController.java b/src/main/java/fr/insee/pearljam/api/controller/OrganizationUnitController.java index 2c2c3d01..045842ef 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/OrganizationUnitController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/OrganizationUnitController.java @@ -3,9 +3,9 @@ import java.util.Collections; import java.util.List; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -22,7 +22,6 @@ import fr.insee.pearljam.api.exception.UserAlreadyExistsException; import fr.insee.pearljam.api.service.OrganizationUnitService; import fr.insee.pearljam.api.service.UserService; -import fr.insee.pearljam.api.web.authentication.AuthenticationHelper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -37,7 +36,7 @@ public class OrganizationUnitController { private final OrganizationUnitService organizationUnitService; private final UserService userService; - private final AuthenticationHelper authHelper; + private final AuthenticatedUserService authenticatedUserService; /** * This method is used to post the list of Organizational Units defined in @@ -49,11 +48,9 @@ public class OrganizationUnitController { */ @Operation(summary = "Create Context with Organizational Unit and users associated") @PostMapping(path = "/organization-units") - public ResponseEntity postContext(Authentication auth, - @RequestBody List organizationUnits) { - + public ResponseEntity postContext(@RequestBody List organizationUnits) { + String userId = authenticatedUserService.getCurrentUserId(); Response response; - String userId = authHelper.getUserId(auth); try { response = organizationUnitService.createOrganizationUnits(organizationUnits); } catch (NoOrganizationUnitException | UserAlreadyExistsException e) { @@ -72,10 +69,9 @@ public ResponseEntity postContext(Authentication auth, */ @Operation(summary = "Create Organizational Unit and users associated") @PostMapping(path = "/organization-unit") - public ResponseEntity postOrganizationUnit(Authentication auth, - @RequestBody OrganizationUnitContextDto organizationUnit) { - String callerId = authHelper.getUserId(auth); - log.info("{} try to create a new OU", callerId); + public ResponseEntity postOrganizationUnit(@RequestBody OrganizationUnitContextDto organizationUnit) { + String userId = authenticatedUserService.getCurrentUserId(); + log.info("{} try to create a new OU", userId); Response response; try { response = organizationUnitService.createOrganizationUnits(Collections.singletonList(organizationUnit)); @@ -83,7 +79,7 @@ public ResponseEntity postOrganizationUnit(Authentication auth, log.error(e.getMessage()); response = new Response(e.getMessage(), HttpStatus.BAD_REQUEST); } - log.info("{} POST /organization-unit resulting in {} with response [{}]", callerId, response.getHttpStatus(), + log.info("{} POST /organization-unit resulting in {} with response [{}]", userId, response.getHttpStatus(), response.getMessage()); return new ResponseEntity<>(response.getMessage(), response.getHttpStatus()); } @@ -97,9 +93,8 @@ public ResponseEntity postOrganizationUnit(Authentication auth, */ @Operation(summary = "Create users by organization-unit") @PostMapping(path = "/organization-unit/{id}/users") - public ResponseEntity postUsersByOrganizationUnit(Authentication auth, - @PathVariable(value = "id") String id, @RequestBody List users) { - + public ResponseEntity postUsersByOrganizationUnit(@PathVariable(value = "id") String id, + @RequestBody List users) { Response response; try { response = userService.createUsersByOrganizationUnit(users, id); @@ -120,9 +115,9 @@ public ResponseEntity postUsersByOrganizationUnit(Authentication auth, */ @Operation(summary = "Get all organization-units") @GetMapping(path = "/organization-units") - public ResponseEntity> getOrganizationUnits(Authentication auth) { - String callerId = authHelper.getUserId(auth); - log.info("{} try to get all OUs", callerId); + public ResponseEntity> getOrganizationUnits() { + String userId = authenticatedUserService.getCurrentUserId(); + log.info("{} try to get all OUs", userId); return new ResponseEntity<>(organizationUnitService.findAllOrganizationUnits(), HttpStatus.OK); } @@ -135,12 +130,10 @@ public ResponseEntity> getOrganizationUnits(Aut */ @Operation(summary = "Delete an organization-unit") @DeleteMapping(path = "/organization-unit/{id}") - public ResponseEntity deleteOrganizationUnit(Authentication auth, - @PathVariable(value = "id") String id) { - String callerId = authHelper.getUserId(auth); + public ResponseEntity deleteOrganizationUnit(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); HttpStatus response = organizationUnitService.delete(id); - log.info("{} : DELETE User resulting in {}", callerId, response); + log.info("{} : DELETE User resulting in {}", userId, response); return new ResponseEntity<>(response); } - } diff --git a/src/main/java/fr/insee/pearljam/api/controller/PreferenceController.java b/src/main/java/fr/insee/pearljam/api/controller/PreferenceController.java index dc24acb2..9ed6a149 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/PreferenceController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/PreferenceController.java @@ -2,17 +2,16 @@ import java.util.List; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.PutMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import fr.insee.pearljam.api.service.PreferenceService; -import fr.insee.pearljam.api.web.authentication.AuthenticationHelper; import io.swagger.v3.oas.annotations.Operation; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -24,7 +23,7 @@ public class PreferenceController { private final PreferenceService preferenceService; - private final AuthenticationHelper authHelper; + private final AuthenticatedUserService authenticatedUserService; /** * This method is using to update the state of Survey Units listed in request @@ -36,9 +35,8 @@ public class PreferenceController { */ @Operation(summary = "Update preferences with campaigns listed in request body") @PutMapping(path = "/preferences") - public ResponseEntity updateSurveyUnit(Authentication auth, - @RequestBody List listPreference) { - String userId = authHelper.getUserId(auth); + public ResponseEntity updateSurveyUnit(@RequestBody List listPreference) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { diff --git a/src/main/java/fr/insee/pearljam/api/controller/StateController.java b/src/main/java/fr/insee/pearljam/api/controller/StateController.java index 27ce45ad..7816e1e5 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/StateController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/StateController.java @@ -2,10 +2,10 @@ import java.util.List; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; @@ -17,7 +17,6 @@ import fr.insee.pearljam.api.exception.NotFoundException; import fr.insee.pearljam.api.service.StateService; import fr.insee.pearljam.api.service.UtilsService; -import fr.insee.pearljam.api.web.authentication.AuthenticationHelper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -32,7 +31,7 @@ public class StateController { private final StateService stateService; private final UtilsService utilsService; - private final AuthenticationHelper authHelper; + private final AuthenticatedUserService authenticatedUserService; /** * This method is used to count survey units by states, interviewer and campaign @@ -46,10 +45,10 @@ public class StateController { */ @Operation(summary = "Get interviewerStateCount") @GetMapping(path = "/campaign/{id}/survey-units/interviewer/{idep}/state-count") - public ResponseEntity getInterviewerStateCount(Authentication auth, + public ResponseEntity getInterviewerStateCount( @PathVariable(value = "id") String id, @PathVariable(value = "idep") String idep, @RequestParam(required = false, name = "date") Long date) { - String userId = authHelper.getUserId(auth); + String userId = authenticatedUserService.getCurrentUserId(); List associatedOrgUnits = utilsService.getRelatedOrganizationUnits(userId); if (StringUtils.isBlank(userId)) { @@ -79,9 +78,10 @@ public ResponseEntity getInterviewerStateCount(Authentication aut */ @Operation(summary = "Get state count for non attributted SUs") @GetMapping(path = "/campaign/{id}/survey-units/not-attributed/state-count") - public ResponseEntity getNbSUNotAttributedStateCount(Authentication auth, - @PathVariable(value = "id") String id, @RequestParam(required = false, name = "date") Long date) { - String userId = authHelper.getUserId(auth); + public ResponseEntity getNbSUNotAttributedStateCount( + @PathVariable(value = "id") String id, + @RequestParam(required = false, name = "date") Long date) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { @@ -110,9 +110,10 @@ public ResponseEntity getNbSUNotAttributedStateCount(Authenticati */ @Operation(summary = "Get campaignStateCount") @GetMapping(path = "/campaign/{id}/survey-units/state-count") - public ResponseEntity getCampaignStateCount(Authentication auth, - @PathVariable(value = "id") String id, @RequestParam(required = false, name = "date") Long date) { - String userId = authHelper.getUserId(auth); + public ResponseEntity getCampaignStateCount( + @PathVariable(value = "id") String id, + @RequestParam(required = false, name = "date") Long date) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { @@ -139,9 +140,9 @@ public ResponseEntity getCampaignStateCount(Authenticatio */ @Operation(summary = "Get interviewersStateCount") @GetMapping(path = "/interviewers/survey-units/state-count") - public ResponseEntity> getInterviewersStateCount(Authentication auth, + public ResponseEntity> getInterviewersStateCount( @RequestParam(required = false, name = "date") Long date) { - String userId = authHelper.getUserId(auth); + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { @@ -165,9 +166,9 @@ public ResponseEntity> getInterviewersStateCount(Authenticat */ @Operation(summary = "Get campaignStateCount") @GetMapping(path = "/campaigns/survey-units/state-count") - public ResponseEntity> getCampaignsStateCount(Authentication auth, - @RequestParam(required = false, name = "date") Long date) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getCampaignsStateCount( + @RequestParam(required = false, name = "date") Long date) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } else { diff --git a/src/main/java/fr/insee/pearljam/api/controller/SurveyUnitController.java b/src/main/java/fr/insee/pearljam/api/controller/SurveyUnitController.java index 322af92d..2711fcca 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/SurveyUnitController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/SurveyUnitController.java @@ -4,6 +4,7 @@ import java.util.Optional; import java.util.Set; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; import jakarta.servlet.http.HttpServletRequest; import com.fasterxml.jackson.databind.JsonNode; @@ -12,7 +13,6 @@ import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatusCode; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -23,7 +23,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import fr.insee.pearljam.api.configuration.auth.AuthorityRoleEnum; +import fr.insee.pearljam.domain.security.model.AuthorityRole; import fr.insee.pearljam.api.constants.Constants; import fr.insee.pearljam.api.dto.comment.CommentDto; import fr.insee.pearljam.api.dto.state.StateDto; @@ -37,14 +37,11 @@ import fr.insee.pearljam.api.exception.NotFoundException; import fr.insee.pearljam.api.exception.SurveyUnitException; import fr.insee.pearljam.api.service.SurveyUnitService; -import fr.insee.pearljam.api.web.authentication.AuthenticationHelper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import static fr.insee.pearljam.api.configuration.auth.AuthorityRole.autorityContainsRole; - /** * SurveyUnitController is the Controller managing {@link SurveyUnit} * entity @@ -60,10 +57,8 @@ public class SurveyUnitController { private static final String GUEST = "GUEST"; - private final SurveyUnitService surveyUnitService; - - private final AuthenticationHelper authHelper; + private final AuthenticatedUserService authenticatedUserService; public static final String GET_SURVEY_UNIT_WITH_ID = "{} : GET SurveyUnit with id {} resulting in {}"; @@ -75,9 +70,7 @@ public class SurveyUnitController { */ @Operation(summary = "Create survey-units") @PostMapping(path = "/survey-units") - public ResponseEntity postSurveyUnits(Authentication auth, - @RequestBody List surveyUnits) { - + public ResponseEntity postSurveyUnits(@RequestBody List surveyUnits) { Response response = surveyUnitService.createSurveyUnits(surveyUnits); log.info("POST /survey-units resulting in {} with response [{}]", response.getHttpStatus(), response.getMessage()); @@ -93,9 +86,7 @@ public ResponseEntity postSurveyUnits(Authentication auth, */ @Operation(summary = "Assign SurveyUnits to interviewers") @PostMapping(path = "/survey-units/interviewers") - public ResponseEntity postSurveyUnitInterviewerLinks(Authentication auth, - @RequestBody List surveyUnits) { - + public ResponseEntity postSurveyUnitInterviewerLinks(@RequestBody List surveyUnits) { Response response = surveyUnitService.createSurveyUnitInterviewerLinks(surveyUnits); log.info("POST /survey-units/interviewers resulting in {} with response [{}]", response.getHttpStatus(), response.getMessage()); @@ -111,9 +102,9 @@ public ResponseEntity postSurveyUnitInterviewerLinks(Authentication auth */ @Operation(summary = "Get SurveyUnits") @GetMapping(path = "/survey-units") - public ResponseEntity> getListSurveyUnit(Authentication auth, - @RequestParam(value = "extended", defaultValue = "false", required = false) Boolean extended) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getListSurveyUnit( + @RequestParam(value = "extended", defaultValue = "false", required = false) Boolean extended) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -135,9 +126,8 @@ public ResponseEntity> getListSurveyUnit(Authentication auth */ @Operation(summary = "Get detail of specific survey unit ") @GetMapping(path = "/survey-unit/{id}") - public ResponseEntity getSurveyUnitById(Authentication auth, - @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity getSurveyUnitById(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -179,9 +169,10 @@ public ResponseEntity getSurveyUnitById(Authentication auth */ @Operation(summary = "Update the Survey Unit") @PutMapping(path = "/survey-unit/{id}") - public ResponseEntity updateSurveyUnit(Authentication auth, - @RequestBody SurveyUnitDetailDto surveyUnitUpdated, @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity updateSurveyUnit( + @RequestBody SurveyUnitDetailDto surveyUnitUpdated, + @PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -197,9 +188,10 @@ public ResponseEntity updateSurveyUnit(Authentication auth, */ @Operation(summary = "Post survey-unit to temp-zone") @PostMapping(path = "/survey-unit/{id}/temp-zone") - public ResponseEntity postSurveyUnitByIdInTempZone(@RequestBody JsonNode surveyUnit, - Authentication auth, @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity postSurveyUnitByIdInTempZone( + @RequestBody JsonNode surveyUnit, + @PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); surveyUnitService.saveSurveyUnitToTempZone(id, userId, surveyUnit); log.info("{} : POST survey-unit {} to temp-zone resulting in 201", userId, id); return new ResponseEntity<>(HttpStatus.CREATED); @@ -227,9 +219,10 @@ public ResponseEntity getSurveyUnitsInTempZone() { */ @Operation(summary = "Update the state of Survey Units listed in request body") @PutMapping(path = "/survey-unit/{id}/state/{state}") - public ResponseEntity updateSurveyUnitState(Authentication auth, - @PathVariable(value = "id") String surveyUnitId, @PathVariable(value = "state") StateType state) { - String userId = authHelper.getUserId(auth); + public ResponseEntity updateSurveyUnitState( + @PathVariable(value = "id") String surveyUnitId, + @PathVariable(value = "state") StateType state) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -250,10 +243,10 @@ public ResponseEntity updateSurveyUnitState(Authentication auth, */ @Operation(summary = "Closes a survey unit") @PutMapping(path = "/survey-unit/{id}/close/{closingCause}") - public ResponseEntity closeSurveyUnit(Authentication auth, + public ResponseEntity closeSurveyUnit( @PathVariable(value = "id") String surveyUnitId, @PathVariable(value = "closingCause") ClosingCauseType closingCause) { - String userId = authHelper.getUserId(auth); + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -275,10 +268,10 @@ public ResponseEntity closeSurveyUnit(Authentication auth, */ @Operation(summary = "Add Closing cause") @PutMapping(path = "/survey-unit/{id}/closing-cause/{closingCause}") - public ResponseEntity updateClosingCause(Authentication auth, + public ResponseEntity updateClosingCause( @PathVariable(value = "id") String surveyUnitId, @PathVariable(value = "closingCause") ClosingCauseType closingCause) { - String userId = authHelper.getUserId(auth); + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -298,9 +291,10 @@ public ResponseEntity updateClosingCause(Authentication auth, */ @Operation(summary = "Update the state of Survey Units listed in request body") @PutMapping(path = "/survey-unit/{id}/comment") - public ResponseEntity updateSurveyUnitComment(Authentication auth, - @RequestBody CommentDto comment, @PathVariable(value = "id") String surveyUnitId) { - String userId = authHelper.getUserId(auth); + public ResponseEntity updateSurveyUnitComment( + @RequestBody CommentDto comment, + @PathVariable(value = "id") String surveyUnitId) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -311,9 +305,8 @@ public ResponseEntity updateSurveyUnitComment(Authentication auth, @Operation(summary = "Update the state of Survey Units listed in request body") @PutMapping(path = "/survey-unit/{id}/viewed") - public ResponseEntity updateSurveyUnitViewed(Authentication auth, - @PathVariable(value = "id") String surveyUnitId) { - String userId = authHelper.getUserId(auth); + public ResponseEntity updateSurveyUnitViewed(@PathVariable(value = "id") String surveyUnitId) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -333,9 +326,10 @@ public ResponseEntity updateSurveyUnitViewed(Authentication auth, */ @Operation(summary = "Get Survey Units in target campaign") @GetMapping(path = "/campaign/{id}/survey-units") - public ResponseEntity> getSurveyUnitByCampaignId(Authentication auth, - @PathVariable(value = "id") String id, @RequestParam(value = "state", required = false) String state) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getSurveyUnitByCampaignId( + @PathVariable(value = "id") String id, + @RequestParam(value = "state", required = false) String state) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { return new ResponseEntity<>(HttpStatus.FORBIDDEN); } @@ -353,10 +347,11 @@ public ResponseEntity> getSurveyUnitByCampaignId(Auth */ @Operation(summary = "Check habilitation") @GetMapping(path = "/check-habilitation") - public ResponseEntity checkHabilitation(Authentication auth, - @RequestParam(value = "id", required = true) String id, + public ResponseEntity checkHabilitation( + @RequestParam(value = "id") String id, @RequestParam(value = "role", required = false) String role) { - String userId = authHelper.getUserId(auth); + + String userId = authenticatedUserService.getCurrentUserId(); HabilitationDto resp = new HabilitationDto(); resp.setHabilitated(false); @@ -366,7 +361,7 @@ public ResponseEntity checkHabilitation(Authentication auth, userId, id); return new ResponseEntity<>(resp, HttpStatus.OK); } - if (autorityContainsRole(auth, AuthorityRoleEnum.ADMIN)) { + if (authenticatedUserService.hasRole(AuthorityRole.ADMIN)) { resp.setHabilitated(true); log.info( "Check habilitation of {} as {} for accessing survey-unit {} resulted in {} : Admin habilitation override", @@ -377,13 +372,12 @@ public ResponseEntity checkHabilitation(Authentication auth, if (role.isBlank()) { // interviewer boolean checkdataBase = surveyUnitService.checkHabilitationInterviewer(userId, id); - boolean checkToken = autorityContainsRole(auth, AuthorityRoleEnum.INTERVIEWER); + boolean checkToken = authenticatedUserService.hasRole(AuthorityRole.INTERVIEWER); resp.setHabilitated(checkdataBase && checkToken); } else if (role.equals(Constants.REVIEWER)) { // local or national user boolean checkdataBase = surveyUnitService.checkHabilitationReviewer(userId, id); - boolean checkToken = autorityContainsRole(auth, AuthorityRoleEnum.LOCAL_USER) - || autorityContainsRole(auth, AuthorityRoleEnum.NATIONAL_USER); + boolean checkToken = authenticatedUserService.hasAnyRole(AuthorityRole.LOCAL_USER, AuthorityRole.NATIONAL_USER); resp.setHabilitated(checkdataBase && checkToken); } log.info("Check habilitation of {} as {} for accessing survey-unit {} resulted in {}", userId, @@ -401,9 +395,10 @@ public ResponseEntity checkHabilitation(Authentication auth, */ @Operation(summary = "Get states of given survey unit") @GetMapping(path = "/survey-unit/{id}/states") - public ResponseEntity getStatesBySurveyUnitId(Authentication auth, + public ResponseEntity getStatesBySurveyUnitId( @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { log.info("GET states of surveyUnit {} resulting in 403", id); return new ResponseEntity<>(HttpStatus.FORBIDDEN); @@ -427,10 +422,9 @@ public ResponseEntity getStatesBySurveyUnitId(Authenticatio */ @Operation(summary = "Get closable survey units") @GetMapping(path = "/survey-units/closable") - public ResponseEntity> getClosableSurveyUnits(HttpServletRequest request, - Authentication auth) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getClosableSurveyUnits(HttpServletRequest request) { + String userId = authenticatedUserService.getCurrentUserId(); log.info("{} try to GET closable units", userId); if (StringUtils.isBlank(userId)) { @@ -450,9 +444,8 @@ public ResponseEntity> getClosableSurveyUnits(HttpSe */ @Operation(summary = "Delete survey-unit") @DeleteMapping(path = "/survey-unit/{id}") - - public ResponseEntity deleteSurveyUnit(Authentication auth, @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity deleteSurveyUnit(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); log.info("{} try to DELETE survey-unit {}", userId, id); Optional surveyUnitOptional = surveyUnitService.findById(id); @@ -473,8 +466,8 @@ public ResponseEntity deleteSurveyUnit(Authentication auth, @PathVariabl */ @Operation(summary = "Get survey units id") @GetMapping(path = "/admin/survey-units") - public ResponseEntity> getAllSurveyUnitsId(Authentication auth) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getAllSurveyUnitsId() { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { log.info("GET admin survey units resulting in 401"); return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); @@ -493,9 +486,8 @@ public ResponseEntity> getAllSurveyUnitsId(Authentication auth) { */ @Operation(summary = "Get survey units id by campaign") @GetMapping(path = "/admin/campaign/{id}/survey-units") - public ResponseEntity> getAllSurveyUnitsIdByCampaignId(Authentication auth, - @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity> getAllSurveyUnitsIdByCampaignId(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { log.info("GET admin survey units for campaign {} resulting in 401", id); return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); diff --git a/src/main/java/fr/insee/pearljam/api/controller/UserController.java b/src/main/java/fr/insee/pearljam/api/controller/UserController.java index eb99a487..a43b66e7 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/UserController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/UserController.java @@ -3,10 +3,10 @@ import java.util.Collections; import java.util.Optional; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; import org.apache.commons.lang3.StringUtils; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; -import org.springframework.security.core.Authentication; import org.springframework.web.bind.annotation.DeleteMapping; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; @@ -23,7 +23,6 @@ import fr.insee.pearljam.api.service.OrganizationUnitService; import fr.insee.pearljam.api.service.PreferenceService; import fr.insee.pearljam.api.service.UserService; -import fr.insee.pearljam.api.web.authentication.AuthenticationHelper; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; @@ -36,12 +35,11 @@ @RequiredArgsConstructor public class UserController { - private final AuthenticationHelper authHelper; - private final UserService userService; private final MessageService messageService; private final OrganizationUnitService organizationUnitService; private final PreferenceService preferenceService; + private final AuthenticatedUserService authenticatedUserService; /** * This method returns the current USER @@ -52,8 +50,8 @@ public class UserController { */ @Operation(summary = "Get User") @GetMapping(path = "/user") - public ResponseEntity getUser(Authentication auth) { - String userId = authHelper.getUserId(auth); + public ResponseEntity getUser() { + String userId = authenticatedUserService.getCurrentUserId(); if (StringUtils.isBlank(userId)) { log.info("GET User resulting in 403"); return new ResponseEntity<>(HttpStatus.FORBIDDEN); @@ -78,8 +76,9 @@ public ResponseEntity getUser(Authentication auth) { */ @Operation(summary = "Get User by id") @GetMapping(path = "/user/{id}") - public ResponseEntity getUserById(Authentication auth, @PathVariable(value = "id") String id) { - String userId = authHelper.getUserId(auth); + public ResponseEntity getUserById( + @PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); log.info("{} try to GET user with id : {}", userId, id); if (StringUtils.isBlank(userId)) { log.info("GET User {} resulting in 403", id); @@ -102,9 +101,10 @@ public ResponseEntity getUserById(Authentication auth, @PathVariable(va */ @Operation(summary = "Create User") @PostMapping(path = "/user") - public ResponseEntity createUser(Authentication auth, @RequestBody UserDto user) { - String callerId = authHelper.getUserId(auth); - log.info("{} try to create a new user", callerId); + public ResponseEntity createUser( + @RequestBody UserDto user) { + String userId = authenticatedUserService.getCurrentUserId(); + log.info("{} try to create a new user", userId); if (!userService.checkValidity(user)) { String invalidUserInfo = String.format("Invalid user : %s", user.toString()); log.info(invalidUserInfo); @@ -138,10 +138,11 @@ public ResponseEntity createUser(Authentication auth, @RequestBody UserD */ @Operation(summary = "Update User") @PutMapping(path = "/user/{id}") - public ResponseEntity updateUser(Authentication auth, @PathVariable(value = "id") String id, + public ResponseEntity updateUser( + @PathVariable(value = "id") String id, @RequestBody UserDto user) { - String callerId = authHelper.getUserId(auth); - log.info("{} try to update user {}", callerId, id); + String userId = authenticatedUserService.getCurrentUserId(); + log.info("{} try to update user {}", userId, id); if (!userService.checkValidity(user)) { String invalidUserInfo = String.format("Invalid user : %s", user.toString()); @@ -170,7 +171,7 @@ public ResponseEntity updateUser(Authentication auth, @PathVariable(valu log.warn(noFoundUser); return new ResponseEntity<>(noFoundUser, HttpStatus.NOT_FOUND); } - log.info("{} updated user {} - {} ", callerId, id, HttpStatus.OK.value()); + log.info("{} updated user {} - {} ", userId, id, HttpStatus.OK.value()); return new ResponseEntity<>(updatedUser, HttpStatus.OK); } @@ -181,9 +182,10 @@ public ResponseEntity updateUser(Authentication auth, @PathVariable(valu */ @Operation(summary = "Assign User to Organization Unit") @PutMapping(path = "/user/{userId}/organization-unit/{ouId}") - public ResponseEntity assignUserToOU(Authentication auth, - @PathVariable(value = "userId") String userId, @PathVariable(value = "ouId") String ouId) { - String callerId = authHelper.getUserId(auth); + public ResponseEntity assignUserToOU( + @PathVariable(value = "userId") String userId, + @PathVariable(value = "ouId") String ouId) { + String callerId = authenticatedUserService.getCurrentUserId(); log.info("{} try to assign user {} to OU {}", callerId, userId, ouId); Optional optUser = userService.getUser(userId); if (optUser.isEmpty()) { @@ -222,9 +224,9 @@ public ResponseEntity assignUserToOU(Authentication auth, */ @Operation(summary = "Delete User") @DeleteMapping(path = "/user/{id}") - public ResponseEntity deleteUser(Authentication auth, @PathVariable(value = "id") String id) { - String callerId = authHelper.getUserId(auth); - log.info("{} try to delete user {}", callerId, id); + public ResponseEntity deleteUser(@PathVariable(value = "id") String id) { + String userId = authenticatedUserService.getCurrentUserId(); + log.info("{} try to delete user {}", userId, id); if (!userService.userIsPresent(id)) { String noFoundUser = String.format("User %s can't be deleted : not found", id); @@ -235,7 +237,7 @@ public ResponseEntity deleteUser(Authentication auth, @PathVariable(valu preferenceService.setPreferences(Collections.emptyList(), id); HttpStatus response = userService.delete(id); - log.info("{} : DELETE User {} resulting in {}", callerId, id, response.value()); + log.info("{} : DELETE User {} resulting in {}", userId, id, response.value()); return new ResponseEntity<>(response); } } diff --git a/src/main/java/fr/insee/pearljam/api/service/UtilsService.java b/src/main/java/fr/insee/pearljam/api/service/UtilsService.java index fea07110..036b78dd 100644 --- a/src/main/java/fr/insee/pearljam/api/service/UtilsService.java +++ b/src/main/java/fr/insee/pearljam/api/service/UtilsService.java @@ -10,20 +10,6 @@ public interface UtilsService { - /** - * This method retrieve the UserId passed in the HttpServletRequest - * @param HttpServletRequest - * @return {@link String} of UserId - */ - String getUserId(HttpServletRequest request); - - /** - * This method check if the current User exist or not in database - * @param userId - * @return {@link Boolean} - */ - boolean existUser(String userId, String service); - /** * @param userId * @param campaignId diff --git a/src/main/java/fr/insee/pearljam/api/service/impl/DataSetInjectorServiceImpl.java b/src/main/java/fr/insee/pearljam/api/service/impl/DataSetInjectorServiceImpl.java index 3fe104af..211c7440 100644 --- a/src/main/java/fr/insee/pearljam/api/service/impl/DataSetInjectorServiceImpl.java +++ b/src/main/java/fr/insee/pearljam/api/service/impl/DataSetInjectorServiceImpl.java @@ -178,6 +178,7 @@ public HttpStatus createDataSet() { // create user entities userRepository.save(new User("ABC", "Melinda", "Webb", ouNorth)); + userRepository.save(new User("GUEST", "firstname", "lastname", ouNorth)); userRepository.save(new User("DEF", "Everett", "Juste", ouNorth)); User user3 = userRepository.save(new User("GHI", "Elsie", "Clarke", ouSouth)); User user4 = userRepository.save(new User("JKL", "Julius", "Howell", ouNational)); diff --git a/src/main/java/fr/insee/pearljam/api/service/impl/UserServiceImpl.java b/src/main/java/fr/insee/pearljam/api/service/impl/UserServiceImpl.java index d3100815..7296e891 100644 --- a/src/main/java/fr/insee/pearljam/api/service/impl/UserServiceImpl.java +++ b/src/main/java/fr/insee/pearljam/api/service/impl/UserServiceImpl.java @@ -6,13 +6,12 @@ import java.util.Optional; import java.util.stream.Collectors; +import fr.insee.pearljam.infrastructure.security.config.OidcProperties; import jakarta.transaction.Transactional; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Service; -import fr.insee.pearljam.api.configuration.properties.ApplicationProperties; -import fr.insee.pearljam.api.configuration.properties.AuthEnumProperties; import fr.insee.pearljam.api.constants.Constants; import fr.insee.pearljam.api.domain.OrganizationUnit; import fr.insee.pearljam.api.domain.Response; @@ -43,11 +42,11 @@ public class UserServiceImpl implements UserService { private final UserRepository userRepository; private final CampaignRepository campaignRepository; private final OrganizationUnitRepository ouRepository; - private final ApplicationProperties applicationProperties; + private final OidcProperties oidcProperties; public Optional getUser(String userId) { List organizationUnits = new ArrayList<>(); - if (applicationProperties.auth() != AuthEnumProperties.NOAUTH) { + if (oidcProperties.enabled()) { Optional user = userRepository.findByIdIgnoreCase(userId); OrganizationUnitDto organizationUnitsParent = new OrganizationUnitDto(); @@ -62,11 +61,11 @@ public Optional getUser(String userId) { return Optional.empty(); } } else { - Optional ouNat = ouRepository.findByIdIgnoreCase(applicationProperties.guestOU()); + Optional ouNat = ouRepository.findByIdIgnoreCase("OU-NORTH"); if (ouNat.isPresent()) { getOrganizationUnits(organizationUnits, ouNat.get(), false); Optional ou = ouRepository - .findDtoByIdIgnoreCase(applicationProperties.guestOU()); + .findDtoByIdIgnoreCase("OU-NORTH"); if (ou.isPresent()) { return Optional.of(new UserDto("", "Guest", "", ou.get(), organizationUnits)); } @@ -103,7 +102,7 @@ public List getUserOUs(String userId, boolean saveAllLevels getOrganizationUnits(organizationUnits, user.get().getOrganizationUnit(), saveAllLevels); } } else { - Optional ouNat = ouRepository.findByIdIgnoreCase(applicationProperties.guestOU()); + Optional ouNat = ouRepository.findByIdIgnoreCase("OU-NORTH"); if (ouNat.isPresent()) { getOrganizationUnits(organizationUnits, ouNat.get(), saveAllLevels); } else { diff --git a/src/main/java/fr/insee/pearljam/api/service/impl/UtilsServiceImpl.java b/src/main/java/fr/insee/pearljam/api/service/impl/UtilsServiceImpl.java index 51a699c1..06407705 100644 --- a/src/main/java/fr/insee/pearljam/api/service/impl/UtilsServiceImpl.java +++ b/src/main/java/fr/insee/pearljam/api/service/impl/UtilsServiceImpl.java @@ -12,12 +12,10 @@ import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import fr.insee.pearljam.api.configuration.properties.ApplicationProperties; -import fr.insee.pearljam.api.configuration.properties.AuthEnumProperties; import fr.insee.pearljam.api.configuration.properties.ExternalServicesProperties; import fr.insee.pearljam.api.constants.Constants; import fr.insee.pearljam.api.domain.User; @@ -36,9 +34,7 @@ @RequiredArgsConstructor public class UtilsServiceImpl implements UtilsService { - private final ApplicationProperties applicationProperties; private final ExternalServicesProperties externalServicesProperties; - private final InterviewerRepository interviewerRepository; private final UserRepository userRepository; private final CampaignRepository campaignRepository; private final OrganizationUnitRepository organizationUnitRepository; @@ -46,27 +42,6 @@ public class UtilsServiceImpl implements UtilsService { private final RestTemplate restTemplate; private final Environment environment; - public String getUserId(HttpServletRequest request) { - if (applicationProperties.auth() == AuthEnumProperties.KEYCLOAK) { - JwtAuthenticationToken keycloak = (JwtAuthenticationToken) request.getUserPrincipal(); - return keycloak.getPrincipal().toString(); - } - - return Constants.GUEST; - } - - public boolean existUser(String userId, String service) { - if (service.equals(Constants.INTERVIEWER)) { - return Constants.GUEST.equals(userId) || interviewerRepository.findByIdIgnoreCase(userId).isPresent(); - } else if (service.equals(Constants.USER)) { - return Constants.GUEST.equals(userId) || userRepository.findByIdIgnoreCase(userId).isPresent(); - } else { - log.info("Choose a correct service"); - return false; - } - - } - public List getRelatedOrganizationUnits(String userId) { List l = new ArrayList<>(); Optional user = userRepository.findByIdIgnoreCase(userId); diff --git a/src/main/java/fr/insee/pearljam/api/web/authentication/AuthenticationHelper.java b/src/main/java/fr/insee/pearljam/api/web/authentication/AuthenticationHelper.java deleted file mode 100644 index f0272059..00000000 --- a/src/main/java/fr/insee/pearljam/api/web/authentication/AuthenticationHelper.java +++ /dev/null @@ -1,28 +0,0 @@ -package fr.insee.pearljam.api.web.authentication; - -import org.springframework.security.core.Authentication; - -public interface AuthenticationHelper { - /** - * Retrieve the auth token of the current user - * - * @param auth authenticated user - * @return auth token - */ - String getAuthToken(Authentication auth); - - /** - * Retrieve the user id from the current user - * - * @param authentication authenticated user - * @return the user id - */ - String getUserId(Authentication authentication); - - /** - * Retrieve the authentication principal for current user - * - * @return {@link Authentication} the authentication user object - */ - Authentication getAuthenticationPrincipal(); -} \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/api/web/authentication/AuthenticationTokenException.java b/src/main/java/fr/insee/pearljam/api/web/authentication/AuthenticationTokenException.java deleted file mode 100644 index 3c7e6e03..00000000 --- a/src/main/java/fr/insee/pearljam/api/web/authentication/AuthenticationTokenException.java +++ /dev/null @@ -1,7 +0,0 @@ -package fr.insee.pearljam.api.web.authentication; - -public class AuthenticationTokenException extends RuntimeException { - public AuthenticationTokenException(String message) { - super(message); - } -} diff --git a/src/main/java/fr/insee/pearljam/api/web/authentication/AuthenticationUserHelper.java b/src/main/java/fr/insee/pearljam/api/web/authentication/AuthenticationUserHelper.java deleted file mode 100644 index f8b74f69..00000000 --- a/src/main/java/fr/insee/pearljam/api/web/authentication/AuthenticationUserHelper.java +++ /dev/null @@ -1,46 +0,0 @@ -package fr.insee.pearljam.api.web.authentication; - -import fr.insee.pearljam.api.configuration.auth.AuthConstants; -import fr.insee.pearljam.api.configuration.properties.ApplicationProperties; -import lombok.AllArgsConstructor; -import org.springframework.security.core.Authentication; -import org.springframework.security.core.context.SecurityContextHolder; -import org.springframework.security.oauth2.core.AbstractOAuth2Token; -import org.springframework.security.oauth2.jwt.Jwt; -import org.springframework.stereotype.Component; - -@Component -@AllArgsConstructor -public class AuthenticationUserHelper implements AuthenticationHelper { - private final ApplicationProperties applicationProperties; - - @Override - public String getAuthToken(Authentication auth) { - if (auth == null) { - throw new AuthenticationTokenException("Cannot retrieve token for the user."); - } - AbstractOAuth2Token token = (AbstractOAuth2Token) auth.getCredentials(); - return token.getTokenValue(); - } - - @Override - public String getUserId(Authentication authentication) { - switch (applicationProperties.auth()) { - case NOAUTH -> { - return AuthConstants.GUEST; - } - case KEYCLOAK -> { - if (authentication.getCredentials() instanceof Jwt jwt) { - return jwt.getClaims().get(AuthConstants.PREFERRED_USERNAME).toString(); - } - throw new AuthenticationTokenException("Cannot retrieve token for the user."); - } - default -> throw new AuthenticationTokenException("No authentication mode used"); - } - } - - @Override - public Authentication getAuthenticationPrincipal() { - return SecurityContextHolder.getContext().getAuthentication(); - } -} diff --git a/src/main/java/fr/insee/pearljam/api/web/exception/ExceptionControllerAdvice.java b/src/main/java/fr/insee/pearljam/api/web/exception/ExceptionControllerAdvice.java index f3d97eba..bc31895e 100644 --- a/src/main/java/fr/insee/pearljam/api/web/exception/ExceptionControllerAdvice.java +++ b/src/main/java/fr/insee/pearljam/api/web/exception/ExceptionControllerAdvice.java @@ -2,7 +2,6 @@ import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.JsonMappingException; -import fr.insee.pearljam.api.web.authentication.AuthenticationTokenException; import jakarta.validation.ConstraintViolationException; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; @@ -137,14 +136,6 @@ public void noEntityFoundException(EntityNotFoundException e, WebRequest request processException(e, HttpStatus.NOT_FOUND, request); } - @ExceptionHandler(AuthenticationTokenException.class) - @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) - @ResponseBody - public void authenticationTokenExceptionException(AuthenticationTokenException e, WebRequest request) { - log.error(e.getMessage(), e); - processException(e, HttpStatus.INTERNAL_SERVER_ERROR, request, ERROR_OCCURRED_LABEL); - } - @ExceptionHandler(EntityAlreadyExistException.class) @ResponseStatus(HttpStatus.BAD_REQUEST) @ResponseBody diff --git a/src/main/java/fr/insee/pearljam/domain/security/model/AuthorityRole.java b/src/main/java/fr/insee/pearljam/domain/security/model/AuthorityRole.java new file mode 100644 index 00000000..23b87556 --- /dev/null +++ b/src/main/java/fr/insee/pearljam/domain/security/model/AuthorityRole.java @@ -0,0 +1,18 @@ +package fr.insee.pearljam.domain.security.model; + +/** + * Application roles + */ +public enum AuthorityRole { + ADMIN, + WEBCLIENT, + LOCAL_USER, + NATIONAL_USER, + INTERVIEWER; + + public static final String ROLE_PREFIX = "ROLE_"; + + public String securityRole() { + return ROLE_PREFIX + this.name(); + } +} diff --git a/src/main/java/fr/insee/pearljam/domain/security/port/serverside/AuthenticatedUserHelperPort.java b/src/main/java/fr/insee/pearljam/domain/security/port/serverside/AuthenticatedUserHelperPort.java new file mode 100644 index 00000000..643076d9 --- /dev/null +++ b/src/main/java/fr/insee/pearljam/domain/security/port/serverside/AuthenticatedUserHelperPort.java @@ -0,0 +1,28 @@ +package fr.insee.pearljam.domain.security.port.serverside; + +import fr.insee.pearljam.domain.security.model.AuthorityRole; + +/** + * Helper used to retrieve current user information + */ +public interface AuthenticatedUserHelperPort { + /** + * Retrieve current user id + * @return id of the current authenticated user + */ + String getCurrentUserId(); + + /** + * Check if the current authenticated user has a specific role + * @param role role to check + * @return true if the current user has the specific role + */ + boolean hasRole(AuthorityRole role); + + /** + * Check if the current authenticated user has any of the specified roles + * @param roles roles to check + * @return true if the current user has one of the specified roles + */ + boolean hasAnyRole(AuthorityRole... roles); +} diff --git a/src/main/java/fr/insee/pearljam/domain/security/port/userside/AuthenticatedUserService.java b/src/main/java/fr/insee/pearljam/domain/security/port/userside/AuthenticatedUserService.java new file mode 100644 index 00000000..044e8266 --- /dev/null +++ b/src/main/java/fr/insee/pearljam/domain/security/port/userside/AuthenticatedUserService.java @@ -0,0 +1,29 @@ +package fr.insee.pearljam.domain.security.port.userside; + +import fr.insee.pearljam.domain.security.model.AuthorityRole; + +/** + * Service used to retrieve current user information + */ +public interface AuthenticatedUserService { + + /** + * Retrieve current user id + * @return id of the current authenticated user + */ + String getCurrentUserId(); + + /** + * Check if the current authenticated user has a specific role + * @param role role to check + * @return true if the current user has the specific role + */ + boolean hasRole(AuthorityRole role); + + /** + * Check if the current authenticated user has any of the specified roles + * @param roles roles to check + * @return true if the current user has one of the specified roles + */ + boolean hasAnyRole(AuthorityRole... roles); +} \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/domain/security/service/AuthenticationCurrentUserService.java b/src/main/java/fr/insee/pearljam/domain/security/service/AuthenticationCurrentUserService.java new file mode 100644 index 00000000..9c6cd9f4 --- /dev/null +++ b/src/main/java/fr/insee/pearljam/domain/security/service/AuthenticationCurrentUserService.java @@ -0,0 +1,29 @@ +package fr.insee.pearljam.domain.security.service; + +import fr.insee.pearljam.domain.security.port.serverside.AuthenticatedUserHelperPort; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; +import fr.insee.pearljam.domain.security.model.AuthorityRole; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; + +@Service +@RequiredArgsConstructor +public class AuthenticationCurrentUserService implements AuthenticatedUserService { + + private final AuthenticatedUserHelperPort currentUserHelper; + + @Override + public String getCurrentUserId() { + return currentUserHelper.getCurrentUserId(); + } + + @Override + public boolean hasRole(AuthorityRole role) { + return currentUserHelper.hasRole(role); + } + + @Override + public boolean hasAnyRole(AuthorityRole... roles) { + return currentUserHelper.hasAnyRole(roles); + } +} diff --git a/src/main/java/fr/insee/pearljam/infrastructure/security/adapter/AuthenticatedCurrentUserHelperAdapter.java b/src/main/java/fr/insee/pearljam/infrastructure/security/adapter/AuthenticatedCurrentUserHelperAdapter.java new file mode 100644 index 00000000..038fff8b --- /dev/null +++ b/src/main/java/fr/insee/pearljam/infrastructure/security/adapter/AuthenticatedCurrentUserHelperAdapter.java @@ -0,0 +1,38 @@ +package fr.insee.pearljam.infrastructure.security.adapter; + +import fr.insee.pearljam.domain.security.port.serverside.AuthenticatedUserHelperPort; +import fr.insee.pearljam.domain.security.model.AuthorityRole; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.stereotype.Component; + +import java.util.Arrays; + +@Component +@RequiredArgsConstructor +public class AuthenticatedCurrentUserHelperAdapter implements AuthenticatedUserHelperPort { + + @Override + public String getCurrentUserId() { + return getAuthenticationPrincipal().getName(); + } + + @Override + public boolean hasRole(AuthorityRole role) { + return getAuthenticationPrincipal().getAuthorities().stream() + .map(GrantedAuthority::getAuthority) + .anyMatch(authority -> authority.contains(role.securityRole())); + } + + @Override + public boolean hasAnyRole(AuthorityRole... roles) { + return Arrays.stream(roles) + .anyMatch(this::hasRole); + } + + private Authentication getAuthenticationPrincipal() { + return SecurityContextHolder.getContext().getAuthentication(); + } +} diff --git a/src/main/java/fr/insee/pearljam/infrastructure/security/config/GrantedAuthorityConverter.java b/src/main/java/fr/insee/pearljam/infrastructure/security/config/GrantedAuthorityConverter.java new file mode 100644 index 00000000..16e0ef4c --- /dev/null +++ b/src/main/java/fr/insee/pearljam/infrastructure/security/config/GrantedAuthorityConverter.java @@ -0,0 +1,54 @@ +package fr.insee.pearljam.infrastructure.security.config; + +import fr.insee.pearljam.api.configuration.properties.RoleProperties; +import lombok.AllArgsConstructor; +import fr.insee.pearljam.domain.security.model.AuthorityRole; + +import org.springframework.core.convert.converter.Converter; +import org.springframework.lang.NonNull; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.jwt.Jwt; + +import java.util.*; +import java.util.stream.Collectors; + +/** + * Converter used to map roles from jwt token to app roles + */ +@AllArgsConstructor +public class GrantedAuthorityConverter implements Converter> { + public static final String REALM_ACCESS_ROLE = "roles"; + public static final String REALM_ACCESS = "realm_access"; + + private final Map grantedRoles; + + public GrantedAuthorityConverter(RoleProperties roleProperties) { + this.grantedRoles = new HashMap<>(); + this.grantedRoles.put(roleProperties.local_user(), + new SimpleGrantedAuthority(AuthorityRole.LOCAL_USER.securityRole())); + this.grantedRoles.put(roleProperties.national_user(), + new SimpleGrantedAuthority(AuthorityRole.NATIONAL_USER.securityRole())); + this.grantedRoles.put(roleProperties.interviewer(), + new SimpleGrantedAuthority(AuthorityRole.INTERVIEWER.securityRole())); + this.grantedRoles.put(roleProperties.admin(), + new SimpleGrantedAuthority(AuthorityRole.ADMIN.securityRole())); + this.grantedRoles.put(roleProperties.webclient(), + new SimpleGrantedAuthority(AuthorityRole.WEBCLIENT.securityRole())); + } + + @SuppressWarnings("unchecked") + @Override + public Collection convert(@NonNull Jwt jwt) { + Map claims = jwt.getClaims(); + Map realmAccess = (Map) claims.get(REALM_ACCESS); + List roles = (List) realmAccess.get(REALM_ACCESS_ROLE); + + return roles.stream() + .filter(Objects::nonNull) + .filter(role -> !role.isBlank()) + .filter(grantedRoles::containsKey) + .map(grantedRoles::get) + .collect(Collectors.toCollection(ArrayList::new)); + } +} \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/infrastructure/security/config/NoAuthSecurityConfiguration.java b/src/main/java/fr/insee/pearljam/infrastructure/security/config/NoAuthSecurityConfiguration.java new file mode 100644 index 00000000..991e890c --- /dev/null +++ b/src/main/java/fr/insee/pearljam/infrastructure/security/config/NoAuthSecurityConfiguration.java @@ -0,0 +1,110 @@ +package fr.insee.pearljam.infrastructure.security.config; + +import fr.insee.pearljam.domain.security.model.AuthorityRole; +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpFilter; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.authentication.preauth.AbstractPreAuthenticatedProcessingFilter; +import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter; +import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter; + +import java.io.IOException; +import java.time.Instant; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + +/** + * Spring security configuration when using OIDC auth + */ +@ConditionalOnProperty(name = "feature.oidc.enabled", havingValue = "false") +@Configuration +@EnableWebSecurity +@RequiredArgsConstructor +public class NoAuthSecurityConfiguration { + private final OidcProperties oidcProperties; + + @Bean + @Order(1) + @ConditionalOnProperty(name = "feature.swagger.enabled", havingValue = "true") + protected SecurityFilterChain swaggerSecurityFilterChain(HttpSecurity http, + SpringDocSecurityFilterChain springDocSecurityFilterChain) throws Exception { + return springDocSecurityFilterChain.buildSecurityFilterChain(http); + } + + /** + * Configure spring security filter chain when no authentication + * + * @param http Http Security Object + * @return the spring security filter + * @throws Exception exception + */ + @Bean + @Order(2) + protected SecurityFilterChain filterChain(HttpSecurity http) throws Exception { + return http + .securityMatcher("/**") + .csrf(AbstractHttpConfigurer::disable) + .cors(Customizer.withDefaults()) + .headers(headers -> headers + .xssProtection(xssConfig -> xssConfig.headerValue(XXssProtectionHeaderWriter.HeaderValue.DISABLED)) + .contentSecurityPolicy(cspConfig -> cspConfig + .policyDirectives("default-src 'none'") + ) + .referrerPolicy(referrerPolicy -> + referrerPolicy + .policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN) + )) + .addFilterBefore(guestAuthenticationFilter(), AbstractPreAuthenticatedProcessingFilter.class) + .authorizeHttpRequests(authorize -> authorize.anyRequest() + .permitAll()) + .build(); + } + + /** + * Filter used to have an authenticated admin user when oidc is disabled + * @return the filter + */ + private Filter guestAuthenticationFilter() { + return new HttpFilter() { + @Override + protected void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException { + String username = "GUEST"; + + List authorities = new ArrayList<>(); + authorities.add(new SimpleGrantedAuthority(AuthorityRole.ADMIN.securityRole())); + authorities.add(new SimpleGrantedAuthority(AuthorityRole.INTERVIEWER.securityRole())); + + Map headers = Map.of("typ", "JWT"); + Map claims = Map.of(oidcProperties.principalAttribute(), username, "name", username); + + Jwt jwt = new Jwt("token-value", Instant.MIN, Instant.MAX, headers, claims); + JwtAuthenticationToken authentication = new JwtAuthenticationToken(jwt, authorities, username); + + // Set the authentication token in the SecurityContextHolder + SecurityContextHolder.getContext().setAuthentication(authentication); + + // Proceed with the request + chain.doFilter(request, response); + } + }; + } +} \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/api/configuration/properties/KeycloakProperties.java b/src/main/java/fr/insee/pearljam/infrastructure/security/config/OidcProperties.java similarity index 53% rename from src/main/java/fr/insee/pearljam/api/configuration/properties/KeycloakProperties.java rename to src/main/java/fr/insee/pearljam/infrastructure/security/config/OidcProperties.java index 990bdf39..0924e628 100644 --- a/src/main/java/fr/insee/pearljam/api/configuration/properties/KeycloakProperties.java +++ b/src/main/java/fr/insee/pearljam/infrastructure/security/config/OidcProperties.java @@ -1,9 +1,11 @@ -package fr.insee.pearljam.api.configuration.properties; +package fr.insee.pearljam.infrastructure.security.config; import org.springframework.boot.context.properties.ConfigurationProperties; -@ConfigurationProperties(prefix = "application.security.keycloak") -public record KeycloakProperties( +@ConfigurationProperties(prefix = "feature.oidc") +public record OidcProperties( + boolean enabled, + String applicationHost, String authServerHost, String authServerUrl, String realm, diff --git a/src/main/java/fr/insee/pearljam/infrastructure/security/config/OidcSecurityConfiguration.java b/src/main/java/fr/insee/pearljam/infrastructure/security/config/OidcSecurityConfiguration.java new file mode 100644 index 00000000..6710ec17 --- /dev/null +++ b/src/main/java/fr/insee/pearljam/infrastructure/security/config/OidcSecurityConfiguration.java @@ -0,0 +1,271 @@ +package fr.insee.pearljam.infrastructure.security.config; + +import java.util.Collection; + +import fr.insee.pearljam.api.constants.Constants; +import fr.insee.pearljam.domain.security.model.AuthorityRole; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.annotation.Order; +import org.springframework.core.convert.converter.Converter; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.Customizer; +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.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.oauth2.jwt.Jwt; +import org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationConverter; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter; +import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter; + +import fr.insee.pearljam.api.configuration.properties.RoleProperties; +import lombok.RequiredArgsConstructor; + +/** + * Spring security configuration when using OIDC auth + */ +@Configuration +@ConditionalOnProperty(name = "feature.oidc.enabled", havingValue = "true") +@EnableWebSecurity +@EnableMethodSecurity +@RequiredArgsConstructor +public class OidcSecurityConfiguration { + private final OidcProperties oidcProperties; + + /** + * Configure spring security filter chain to handle swagger urls + * + * @param http Http Security configuration object + * @param oidcProperties oidc properties + * @return the spring security filter chain + * @throws Exception exception + */ + @Bean + @Order(1) + @ConditionalOnProperty(name = "feature.swagger.enabled", havingValue = "true") + protected SecurityFilterChain swaggerSecurityFilterChain(HttpSecurity http, + SpringDocSecurityFilterChain springDocSecurityFilterChain, + OidcProperties oidcProperties) throws Exception { + String authorizedConnectionHost = oidcProperties.enabled() ? + " " + oidcProperties.authServerHost() : ""; + return springDocSecurityFilterChain.buildSecurityFilterChain(http, authorizedConnectionHost); + } + + /** + * + * @param http Http Security configuration object + * @param roleProperties role properties + * @return the spring security filter chain + * @throws Exception exception + */ + @Bean + @Order(2) + protected SecurityFilterChain filterChain(HttpSecurity http, + RoleProperties roleProperties) throws Exception { + + http + .securityMatcher("/**") + .csrf(AbstractHttpConfigurer::disable) + .cors(Customizer.withDefaults()) + .headers(headers -> headers + .xssProtection(xssConfig -> xssConfig.headerValue( + XXssProtectionHeaderWriter.HeaderValue.DISABLED)) + .contentSecurityPolicy(cspConfig -> cspConfig.policyDirectives("default-src 'none'")) + .referrerPolicy(referrerPolicy -> referrerPolicy.policy( + ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN))) + .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .oauth2ResourceServer(oauth2 -> oauth2 + .jwt(jwt -> jwt.jwtAuthenticationConverter(jwtAuthenticationConverter(roleProperties)))); + authorizeRequests(http); + return http.build(); + } + + /** + * Add security on endpoints + * @param http Http security configuration + * @throws Exception exception + */ + private void authorizeRequests(HttpSecurity http) throws Exception { + final String adminRole = AuthorityRole.ADMIN.name(); + final String localUserRole = AuthorityRole.LOCAL_USER.name(); + final String nationalUserRole = AuthorityRole.NATIONAL_USER.name(); + final String interviewerRole = AuthorityRole.INTERVIEWER.name(); + + http + .authorizeHttpRequests(configurer -> configurer + .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() + .requestMatchers(HttpMethod.GET, Constants.API_HEALTH_CHECK).permitAll() + // configuration for endpoints + .requestMatchers(HttpMethod.GET, Constants.API_SURVEYUNITS) + .hasAnyRole(adminRole, interviewerRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_SURVEYUNITS_TEMP_ZONE) + .hasAnyRole(adminRole, interviewerRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.POST, Constants.API_SURVEYUNITS) + .hasRole(adminRole) + .requestMatchers(HttpMethod.POST, Constants.API_SURVEYUNITS_INTERVIEWERS) + .hasRole(adminRole) + .requestMatchers(HttpMethod.GET, Constants.API_SURVEYUNITS_CLOSABLE) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_SURVEYUNIT_ID) + .hasAnyRole(adminRole, interviewerRole) + .requestMatchers(HttpMethod.PUT, Constants.API_SURVEYUNIT_ID) + .hasAnyRole(adminRole, interviewerRole) + .requestMatchers(HttpMethod.POST, Constants.API_SURVEYUNIT_ID_TEMP_ZONE) + .hasAnyRole(adminRole, interviewerRole) + .requestMatchers(HttpMethod.DELETE, Constants.API_SURVEYUNIT_ID) + .hasRole(adminRole) + .requestMatchers(HttpMethod.PUT, Constants.API_SURVEYUNIT_ID_STATE) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_SURVEYUNIT_ID_STATES) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.PUT, Constants.API_SURVEYUNIT_ID_COMMENT) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.PUT, Constants.API_SURVEYUNIT_ID_VIEWED) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.PUT, Constants.API_SURVEYUNIT_ID_CLOSE) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.PUT, Constants.API_SURVEYUNIT_ID_CLOSINGCAUSE) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_ADMIN_CAMPAIGNS) + .hasRole(adminRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGNS) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_INTERVIEWER_CAMPAIGNS) + .hasRole(interviewerRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGNS_SU_STATECOUNT) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGNS_SU_CONTACTOUTCOMES) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.POST, Constants.API_CAMPAIGN) + .hasRole(adminRole) + .requestMatchers(HttpMethod.DELETE, Constants.API_CAMPAIGN_ID) + .hasRole(adminRole) + .requestMatchers(HttpMethod.PUT, Constants.API_CAMPAIGN_ID) + .hasRole(adminRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID) + .hasAnyRole(adminRole, interviewerRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.PUT, Constants.API_CAMPAIGN_COLLECTION_DATES) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_INTERVIEWERS) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SURVEYUNITS) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_ABANDONED) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_NOTATTRIBUTED) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_STATECOUNT) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_INTERVIEWER_STATECOUNT) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_NOT_ATTRIBUTED_STATECOUNT) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_CONTACTOUTCOMES) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_INTERVIEWER_CONTACTOUTCOMES) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_NOT_ATTRIBUTED_CONTACTOUTCOMES) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_SU_INTERVIEWER_CLOSINGCAUSES) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.PUT, Constants.API_CAMPAIGN_ID_OU_ID_VISIBILITY) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_VISIBILITIES) + .hasRole(adminRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGN_ID_REFERENTS) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_CAMPAIGNS_ID_ON_GOING) + .hasRole(adminRole) + .requestMatchers(HttpMethod.GET, Constants.API_INTERVIEWERS) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.POST, Constants.API_INTERVIEWERS) + .hasRole(adminRole) + .requestMatchers(HttpMethod.GET, Constants.API_ADMIN_INTERVIEWERS) + .hasRole(adminRole) + .requestMatchers(HttpMethod.PUT, Constants.API_INTERVIEWER_ID) + .hasRole(adminRole) + .requestMatchers(HttpMethod.DELETE, Constants.API_INTERVIEWER_ID) + .hasRole(adminRole) + .requestMatchers(HttpMethod.GET, Constants.API_INTERVIEWER_ID) + .hasRole(adminRole) + .requestMatchers(HttpMethod.GET, Constants.API_INTERVIEWERS_SU_STATECOUNT) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_INTERVIEWER_ID_CAMPAIGNS) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_USER) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.POST, Constants.API_USER) + .hasRole(adminRole) + .requestMatchers(HttpMethod.GET, Constants.API_USER_ID) + .hasRole(adminRole) + .requestMatchers(HttpMethod.PUT, Constants.API_USER_ID) + .hasRole(adminRole) + .requestMatchers(HttpMethod.DELETE, Constants.API_USER_ID) + .hasRole(adminRole) + .requestMatchers(HttpMethod.PUT, Constants.API_USER_ID_ORGANIZATIONUNIT_ID) + .hasRole(adminRole) + .requestMatchers(HttpMethod.POST, Constants.API_ORGANIZATIONUNIT) + .hasRole(adminRole) + .requestMatchers(HttpMethod.POST, Constants.API_ORGANIZATIONUNITS) + .hasRole(adminRole) + .requestMatchers(HttpMethod.GET, Constants.API_ORGANIZATIONUNITS) + .hasRole(adminRole) + .requestMatchers(HttpMethod.DELETE, Constants.API_ORGANIZATIONUNIT_ID) + .hasRole(adminRole) + .requestMatchers(HttpMethod.POST, Constants.API_ORGANIZATIONUNIT_ID_USERS) + .hasRole(adminRole) + .requestMatchers(HttpMethod.PUT, Constants.API_PREFERENCES) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.POST, Constants.API_MESSAGE) + .hasAnyRole(adminRole, interviewerRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_MESSAGES_ID) + .hasAnyRole(adminRole, interviewerRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.POST, Constants.API_VERIFYNAME) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.GET, Constants.API_MESSAGEHISTORY) + .hasAnyRole(adminRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.PUT, Constants.API_MESSAGE_MARK_AS_READ) + .hasAnyRole(adminRole, interviewerRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.PUT, Constants.API_MESSAGE_MARK_AS_DELETED) + .hasAnyRole(adminRole, interviewerRole, localUserRole, nationalUserRole) + .requestMatchers(HttpMethod.POST, Constants.API_CREATEDATASET) + .hasRole(adminRole) + .requestMatchers(HttpMethod.DELETE, Constants.API_DELETEDATASET) + .hasRole(adminRole) + .requestMatchers(HttpMethod.GET, Constants.API_CHECK_HABILITATION) + .hasAnyRole(adminRole, localUserRole, nationalUserRole, interviewerRole) + .requestMatchers(HttpMethod.POST, Constants.API_MAIL) + .hasAnyRole(adminRole, interviewerRole) + .requestMatchers(HttpMethod.GET, Constants.API_ENUM_STATE) + .hasAnyRole(adminRole, localUserRole, nationalUserRole, interviewerRole) + .requestMatchers(HttpMethod.GET, Constants.API_ENUM_CONTACT_ATTEMPT) + .hasAnyRole(adminRole, localUserRole, nationalUserRole, interviewerRole) + .requestMatchers(HttpMethod.GET, Constants.API_ENUM_CONTACT_OUTCOME) + .hasAnyRole(adminRole, localUserRole, nationalUserRole, interviewerRole) + .requestMatchers(HttpMethod.GET, Constants.API_ADMIN_SURVEYUNITS) + .hasRole(adminRole) + .requestMatchers(HttpMethod.GET, Constants.API_ADMIN_CAMPAIGN_ID_SURVEYUNITS) + .hasRole(adminRole) + .anyRequest() + .denyAll()); + } + + @Bean + protected JwtAuthenticationConverter jwtAuthenticationConverter(RoleProperties roleProperties) { + JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter(); + jwtAuthenticationConverter.setPrincipalClaimName(oidcProperties.principalAttribute()); + jwtAuthenticationConverter + .setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter(roleProperties)); + return jwtAuthenticationConverter; + } + + Converter> jwtGrantedAuthoritiesConverter(RoleProperties roleProperties) { + return new GrantedAuthorityConverter(roleProperties); + } + +} \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/infrastructure/security/config/SpringDocSecurityFilterChain.java b/src/main/java/fr/insee/pearljam/infrastructure/security/config/SpringDocSecurityFilterChain.java new file mode 100644 index 00000000..fcd40eed --- /dev/null +++ b/src/main/java/fr/insee/pearljam/infrastructure/security/config/SpringDocSecurityFilterChain.java @@ -0,0 +1,46 @@ +package fr.insee.pearljam.infrastructure.security.config; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.Customizer; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.header.writers.ReferrerPolicyHeaderWriter; +import org.springframework.security.web.header.writers.XXssProtectionHeaderWriter; + +@Configuration +@ConditionalOnProperty(name = "feature.swagger.enabled", havingValue = "true") +public class SpringDocSecurityFilterChain { + + SecurityFilterChain buildSecurityFilterChain(HttpSecurity http) throws Exception { + return buildSecurityFilterChain(http, ""); + } + + SecurityFilterChain buildSecurityFilterChain(HttpSecurity http, + String authorizedConnectionHost) throws Exception { + String[] swaggerUrls = new String[]{"/swagger-ui/**","/v3/api-docs/**"}; + return http + .securityMatcher(swaggerUrls) + .cors(Customizer.withDefaults()) + .headers(headers -> headers + .xssProtection(xssConfig -> xssConfig.headerValue(XXssProtectionHeaderWriter.HeaderValue.DISABLED)) + .contentSecurityPolicy(cspConfig -> cspConfig + .policyDirectives("default-src 'none'; " + + "connect-src 'self'" + authorizedConnectionHost + "; " + + "img-src 'self' data:; " + + "style-src 'self'; " + + "script-src 'self' 'unsafe-inline'") + ) + .referrerPolicy(referrerPolicy -> + referrerPolicy + .policy(ReferrerPolicyHeaderWriter.ReferrerPolicy.SAME_ORIGIN) + )) + .authorizeHttpRequests(auth -> auth + .anyRequest() + .permitAll() + ) + .sessionManagement(sess -> sess.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) + .build(); + } +} diff --git a/src/main/java/fr/insee/pearljam/infrastructure/security/config/swagger/SpringDocNoAuthConfiguration.java b/src/main/java/fr/insee/pearljam/infrastructure/security/config/swagger/SpringDocNoAuthConfiguration.java new file mode 100644 index 00000000..88e9b573 --- /dev/null +++ b/src/main/java/fr/insee/pearljam/infrastructure/security/config/swagger/SpringDocNoAuthConfiguration.java @@ -0,0 +1,19 @@ +package fr.insee.pearljam.infrastructure.security.config.swagger; + +import io.swagger.v3.oas.models.OpenAPI; +import lombok.RequiredArgsConstructor; +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; + +/** + * Swagger configuration to use no authentication with OpenAPI + */ +@Configuration +@RequiredArgsConstructor +@ConditionalOnProperty(name = "feature.oidc.enabled", havingValue = "false") +public class SpringDocNoAuthConfiguration implements SpringDocSecurityConfiguration { + @Override + public void addSecurity(OpenAPI openAPI) { + // nothing to do as no security here + } +} diff --git a/src/main/java/fr/insee/pearljam/infrastructure/security/config/swagger/SpringDocOidcConfiguration.java b/src/main/java/fr/insee/pearljam/infrastructure/security/config/swagger/SpringDocOidcConfiguration.java new file mode 100644 index 00000000..27da2498 --- /dev/null +++ b/src/main/java/fr/insee/pearljam/infrastructure/security/config/swagger/SpringDocOidcConfiguration.java @@ -0,0 +1,59 @@ +package fr.insee.pearljam.infrastructure.security.config.swagger; + +import java.util.List; + +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; +import org.springframework.context.annotation.Configuration; + +import fr.insee.pearljam.infrastructure.security.config.OidcProperties; +import io.swagger.v3.oas.models.Components; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.security.OAuthFlow; +import io.swagger.v3.oas.models.security.OAuthFlows; +import io.swagger.v3.oas.models.security.Scopes; +import io.swagger.v3.oas.models.security.SecurityRequirement; +import io.swagger.v3.oas.models.security.SecurityScheme; +import io.swagger.v3.oas.models.servers.Server; +import lombok.RequiredArgsConstructor; + +/** + * Swagger configuration to use OIDC authentication with OpenAPI + */ +@Configuration +@RequiredArgsConstructor +@ConditionalOnProperty(name = "feature.oidc.enabled", havingValue = "true") +public class SpringDocOidcConfiguration implements SpringDocSecurityConfiguration { + + private final OidcProperties oidcProperties; + + public static final String SECURITY_SCHEMA_OAUTH2 = "oauth2"; + + @Override + public void addSecurity(OpenAPI openAPI) { + String authUrl = String.format("%s/realms/%s/protocol/openid-connect", + oidcProperties.authServerUrl(), + oidcProperties.realm()); + + openAPI + .addServersItem(new Server().url(oidcProperties.applicationHost())) + .addSecurityItem(new SecurityRequirement().addList(SECURITY_SCHEMA_OAUTH2, List.of("read", "write"))) + .components( + new Components() + .addSecuritySchemes(SECURITY_SCHEMA_OAUTH2, + new SecurityScheme() + .name(SECURITY_SCHEMA_OAUTH2) + .type(SecurityScheme.Type.OAUTH2) + .flows(getFlows(authUrl)))); + } + + private OAuthFlows getFlows(String authUrl) { + OAuthFlows flows = new OAuthFlows(); + OAuthFlow flow = new OAuthFlow(); + Scopes scopes = new Scopes(); + flow.setAuthorizationUrl(authUrl + "/auth"); + flow.setTokenUrl(authUrl + "/token"); + flow.setRefreshUrl(authUrl + "/token"); + flow.setScopes(scopes); + return flows.authorizationCode(flow); + } +} \ No newline at end of file diff --git a/src/main/java/fr/insee/pearljam/infrastructure/security/config/swagger/SpringDocSecurityConfiguration.java b/src/main/java/fr/insee/pearljam/infrastructure/security/config/swagger/SpringDocSecurityConfiguration.java new file mode 100644 index 00000000..5a3858a1 --- /dev/null +++ b/src/main/java/fr/insee/pearljam/infrastructure/security/config/swagger/SpringDocSecurityConfiguration.java @@ -0,0 +1,14 @@ +package fr.insee.pearljam.infrastructure.security.config.swagger; + +import io.swagger.v3.oas.models.OpenAPI; + +/** + * Handling security configuration for spring doc + */ +public interface SpringDocSecurityConfiguration { + /** + * Add security configuration to the OpenAPI object + * @param openAPI configuration object for spring doc + */ + void addSecurity(OpenAPI openAPI); +} diff --git a/src/main/java/lombok.config b/src/main/java/lombok.config index f2026206..74da8257 100644 --- a/src/main/java/lombok.config +++ b/src/main/java/lombok.config @@ -1 +1 @@ -lombok.addLombokGeneratedAnnotation=true +lombok.addLombokGeneratedAnnotation=true \ No newline at end of file diff --git a/src/main/resources/application-dev.properties b/src/main/resources/application-dev.properties deleted file mode 100644 index 97ba887b..00000000 --- a/src/main/resources/application-dev.properties +++ /dev/null @@ -1,21 +0,0 @@ -spring.config.import=optional:file:${HOME}/pearl-api/local.properties - -feature.enableDataset=true -spring.liquibase.contexts=dev -spring.liquibase.changeLog=classpath:db/master.xml -spring.messages.cache-seconds=1 - -# toggle log levels here -spring.jpa.show-sql=true -spring.jpa.properties.hibernate.format_sql=false -logging.level.org.hibernate.SQL=WARN -logging.level.org.hibernate.type.descriptor.sql.BasicBinder=WARN - -# pretty print api responses -spring.jackson.serialization.indent-output=true - -# local database /!\ be carefull, the spring.datasource.url shouldn't be splitted by autoformat ;) -spring.datasource.url=jdbc:h2:mem:testdb;NON_KEYWORDS=user,value;DATABASE_TO_UPPER=TRUE;DEFAULT_NULL_ORDERING=HIGH;INIT=create domain if not exists jsonb as json;MODE=PostgreSQL -spring.datasource.driverClassName=org.h2.Driver -spring.datasource.username=sa -spring.datasource.password=password \ No newline at end of file diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties index 98eb1c1a..2382e3d4 100644 --- a/src/main/resources/application.properties +++ b/src/main/resources/application.properties @@ -1,6 +1,5 @@ spring.application.name=api application.host=http://localhost:8080 -application.public-urls=/swagger-ui/**,/swagger-ui.html,/v3/api-docs/**,/csrf,/,/webjars/**,/swagger-resources/**,/environnement,/healthcheck,/actuator/**,/h2-console/** # Define Roles mapping here application.roles.interviewer=****** @@ -9,14 +8,14 @@ application.roles.national_user=****** application.roles.admin=****** application.roles.webclient=****** -# !! SECURITY MODE !! => KEYCLOAK | NOAUTH -application.auth=NOAUTH -## if auth=KEYCLOAK : uncomment and provide following properties -application.security.keycloak.auth-server-url=https://*******.** -application.security.keycloak.realm=******** -application.security.keycloak.resource=******** -application.security.keycloak.client-id=******* -application.security.keycloak.principal-attribute=******* +feature.swagger.enabled=false +feature.oidc.enabled=true +feature.oidc.application-host=${application.host} +feature.oidc.auth-server-host=https://auth-server.host +feature.oidc.auth-server-url=${feature.oidc.auth-server-host}/auth +feature.oidc.realm=my-realm +feature.oidc.client-id=my-client-id +feature.oidc.principal-attribute=id-claim application.corsOrigins='*' @@ -50,8 +49,10 @@ spring.jpa.properties.cache.use_query_cache=false spring.jpa.properties.generate_statistics=false spring.jpa.properties.hbm2ddl.auto=validate +spring.h2.console.enabled=false + ## if auth=KEYCLOAK : uncomment and provide following property -spring.security.oauth2.resourceserver.jwt.issuer-uri=${application.security.keycloak.auth-server-url}/realms/${application.security.keycloak.realm} +spring.security.oauth2.resourceserver.jwt.issuer-uri=${feature.oidc.auth-server-url}/realms/${feature.oidc.realm} spring.liquibase.enabled=true spring.liquibase.contexts=prod spring.liquibase.defaultSchema=public @@ -60,7 +61,7 @@ spring.liquibase.change-log=classpath:db/master.xml spring.profiles.group.cache-testing=test,test-cache ## if auth=KEYCLOAK : uncomment and provide following properties -# springdoc.swagger-ui.oauth.client-id=${application.security.keycloak.client-id} +# springdoc.swagger-ui.oauth.client-id=${feature.oidc.client-id} # springdoc.swagger-ui.oauth2RedirectUrl=${application.host}/swagger-ui/oauth2-redirect.html springdoc.swagger-ui.path=/ diff --git a/src/main/resources/dataset/delete_data.sql b/src/main/resources/dataset/delete_data.sql index 38dae1e3..bade8bdc 100644 --- a/src/main/resources/dataset/delete_data.sql +++ b/src/main/resources/dataset/delete_data.sql @@ -10,7 +10,7 @@ DELETE FROM public.survey_unit; DELETE FROM public.visibility; DELETE FROM public.preference; DELETE FROM public.campaign; -DELETE FROM public."user"; +DELETE FROM public.user; DELETE FROM public.sample_identifier; DELETE FROM public.interviewer; DELETE FROM public.organization_unit; diff --git a/src/test/java/fr/insee/pearljam/api/authKeycloak/TestAuthKeyCloak.java b/src/test/java/fr/insee/pearljam/api/authKeycloak/TestAuthKeyCloak.java index a7ba42bd..715602c0 100644 --- a/src/test/java/fr/insee/pearljam/api/authKeycloak/TestAuthKeyCloak.java +++ b/src/test/java/fr/insee/pearljam/api/authKeycloak/TestAuthKeyCloak.java @@ -28,6 +28,7 @@ import java.util.List; import java.util.Optional; +import fr.insee.pearljam.api.service.*; import org.json.JSONException; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Disabled; @@ -111,17 +112,12 @@ import fr.insee.pearljam.api.repository.SurveyUnitRepository; import fr.insee.pearljam.api.repository.UserRepository; import fr.insee.pearljam.api.repository.VisibilityRepository; -import fr.insee.pearljam.api.service.MessageService; -import fr.insee.pearljam.api.service.PreferenceService; -import fr.insee.pearljam.api.service.ReferentService; -import fr.insee.pearljam.api.service.SurveyUnitService; -import fr.insee.pearljam.api.service.UserService; import fr.insee.pearljam.api.utils.AuthenticatedUserTestHelper; import liquibase.Liquibase; import lombok.RequiredArgsConstructor; /* Test class for Keycloak Authentication */ -@ActiveProfiles("test") +@ActiveProfiles("auth") @AutoConfigureMockMvc @ContextConfiguration @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -144,6 +140,7 @@ class TestAuthKeyCloak { private final ReferentService referentservice; private final MessageService messageService; private final PreferenceService preferenceService; + private final DataSetInjectorService injectorService; private final MockMvc mockMvc; private final RestTemplate restTemplate; @@ -152,20 +149,19 @@ class TestAuthKeyCloak { public Liquibase liquibase; - static Authentication MANAGER = AuthenticatedUserTestHelper.AUTH_MANAGER; + static Authentication LOCAL_USER = AuthenticatedUserTestHelper.AUTH_LOCAL_USER; static Authentication INTERVIEWER = AuthenticatedUserTestHelper.AUTH_INTERVIEWER; + static Authentication ADMIN = AuthenticatedUserTestHelper.AUTH_ADMIN; /** * This method set up the dataBase content * - * @throws Exception - * + * */ @BeforeEach - public void setUp() throws Exception { + public void setUp() { mockServer = MockRestServiceServer.createServer(restTemplate); - mockMvc.perform(post("/api/create-dataset").accept(MediaType.APPLICATION_JSON) - .with(authentication(MANAGER))); + injectorService.createDataSet(); } /** @@ -228,9 +224,9 @@ private boolean testingDates(String dateType, long date) { @Test @Order(1) void testGetUser() throws Exception { - mockMvc.perform(get("/api/user").accept(MediaType.APPLICATION_JSON) - .with(authentication(MANAGER))) + .with(authentication(LOCAL_USER))) + .andDo(print()) .andExpectAll( status().isOk(), jsonPath("$.id").value("ABC"), @@ -248,7 +244,7 @@ void testGetCampaignInterviewerStateCountNotAttributed() throws Exception { mockMvc.perform(get("/api/campaign/SIMPSONS2020X00/survey-units/not-attributed/state-count") .accept(MediaType.APPLICATION_JSON) - .with(authentication(MANAGER))) + .with(authentication(LOCAL_USER))) .andExpectAll( status().isOk(), jsonPath("$.nvmCount").value("0"), @@ -279,7 +275,7 @@ void testGetCampaignInterviewerStateCountNotAttributed() throws Exception { void testGetContactOutcomeCountNotattributed() throws Exception { mockMvc.perform(get( "https://localhost:8080/api/campaign/SIMPSONS2020X00/survey-units/not-attributed/contact-outcomes") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), @@ -335,7 +331,7 @@ void testGetCampaign() throws Exception { String campaignJsonPath = "$.[?(@.id == 'SIMPSONS2020X00')].%s"; mockMvc.perform(get(Constants.API_CAMPAIGNS) - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), @@ -390,7 +386,7 @@ void testGetCampaign() throws Exception { void testGetCampaignInterviewer() throws Exception { String interviewerJsonPath = "$.[?(@.id == 'INTW1')].%s"; mockMvc.perform(get("/api/campaign/SIMPSONS2020X00/interviewers") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), @@ -409,7 +405,7 @@ void testGetCampaignInterviewer() throws Exception { @Order(5) void testGetCampaignInterviewerNotFound() throws Exception { mockMvc.perform(get("/api/campaign/SIMPSONS2020X000000/interviewers") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -426,7 +422,7 @@ void testGetCampaignStateCount() throws Exception { String ouJsonPath = "$.organizationUnits.[?(@.idDem == 'OU-NORTH')].%s"; mockMvc.perform(get("/api/campaign/SIMPSONS2020X00/survey-units/state-count") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), @@ -457,7 +453,7 @@ void testGetCampaignStateCount() throws Exception { void testPutClosingCauseNoPreviousClosingCause() throws Exception { mockMvc.perform(put("/api/survey-unit/11/closing-cause/NPI") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); @@ -476,7 +472,7 @@ void testPutClosingCauseNoPreviousClosingCause() @Order(7) void testGetCampaignStateCountNotFound() throws Exception { mockMvc.perform(get("/api/campaign/test/survey-units/state-count") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -485,7 +481,7 @@ void testGetCampaignStateCountNotFound() throws Exception { @Order(8) void testPutClosingCausePreviousClosingCause() throws Exception { mockMvc.perform(put("/api/survey-unit/11/closing-cause/NPA") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); @@ -500,18 +496,18 @@ void testPutCloseSU() throws Exception { String ouJsonPath = "$.organizationUnits.[?(@.idDem == 'OU-NORTH')].%s"; mockMvc.perform(get("/api/campaign/SIMPSONS2020X00/survey-units/state-count") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll(status().isOk(), checkJsonPath(ouJsonPath, "tbrCount", 4L), checkJsonPath(ouJsonPath, "rowCount", 0L)); mockMvc.perform(put("/api/survey-unit/14/close/ROW") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); mockMvc.perform(get("/api/campaign/SIMPSONS2020X00/survey-units/state-count") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll(status().isOk(), checkJsonPath(ouJsonPath, "tbrCount", 3L), @@ -529,7 +525,7 @@ void testPutCloseSU() throws Exception { @Order(8) void testGetCampaignInterviewerStateCount() throws Exception { mockMvc.perform(get("/api/campaign/SIMPSONS2020X00/survey-units/interviewer/INTW1/state-count") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll(status().isOk(), jsonPath("$.nvmCount").value(0L), @@ -564,7 +560,7 @@ void testGetCampaignInterviewerStateCount() throws Exception { @Order(9) void testGetCampaignInterviewerStateCountNotFoundCampaign() throws Exception { mockMvc.perform(get("/api/campaign/SIMPSONS2020X000000/survey-units/interviewer/INTW1/state-count") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -581,7 +577,7 @@ void testGetCampaignInterviewerStateCountNotFoundCampaign() throws Exception { @Order(10) void testGetCampaignInterviewerStateCountNotFoundIntw() throws Exception { mockMvc.perform(get("/api/campaign/SIMPSONS2020X00/survey-units/interviewer/test/state-count") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -657,7 +653,7 @@ void testGetAllSurveyUnit() throws Exception { jsonPath("$.campaignLabel").value(hasItem("Survey on the Simpsons tv show 2020"))); MvcResult result = mockMvc.perform(get(Constants.API_CAMPAIGNS) - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()) .andReturn(); @@ -685,7 +681,7 @@ void testGetAllSurveyUnit() throws Exception { @Order(13) void testGetSurveyUnitDetailNotFound() throws Exception { mockMvc.perform(get("/api/survey-unit/123456789") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -765,7 +761,7 @@ void testPutSurveyUnitDetail() throws Exception { @Order(15) void testPutSurveyUnitState() throws Exception { mockMvc.perform(put("/api/survey-unit/12/state/WFT") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); @@ -782,7 +778,7 @@ void testPutSurveyUnitState() throws Exception { @Order(16) void testPutSurveyUnitStateStateFalse() throws Exception { mockMvc.perform(put("/api/survey-unit/11/state/test") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isInternalServerError()); } @@ -797,7 +793,7 @@ void testPutSurveyUnitStateStateFalse() throws Exception { @Order(17) void testPutSurveyUnitStateNoSu() throws Exception { mockMvc.perform(put("/api/survey-unit/11/state/AOC") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isForbidden()); } @@ -812,7 +808,7 @@ void testPutSurveyUnitStateNoSu() throws Exception { @Order(18) void testPutPreferences() throws Exception { mockMvc.perform(put("/api/preferences") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON) .content(asJsonString(List.of("SIMPSONS2020X00"))) .contentType(MediaType.APPLICATION_JSON)) @@ -829,7 +825,7 @@ void testPutPreferences() throws Exception { @Order(19) void testPutPreferencesWrongCampaignId() throws Exception { mockMvc.perform(put("/api/preferences") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(""))) .contentType(MediaType.APPLICATION_JSON)) @@ -848,7 +844,7 @@ void testGetCampaignInterviewerClosingCauseCount() throws Exception { // use a beforeEach method to run each test with a cleaned database mockMvc.perform(get("/api/campaign/SIMPSONS2020X00/survey-units/interviewer/INTW1/closing-causes") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll(status().isOk(), jsonPath("$.npaCount").value("1"), @@ -867,7 +863,7 @@ void testGetCampaignInterviewerClosingCauseCount() throws Exception { @Order(20) void testGetNbSuAbandoned() throws Exception { mockMvc.perform(get("/api/campaign/SIMPSONS2020X00/survey-units/abandoned") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll(status().isOk(), jsonPath("$.count").value("0")); @@ -885,7 +881,7 @@ void testGetContactOutcomeCountByCampaign() throws Exception { String ouJsonPath = "$.organizationUnits.[?(@.idDem == 'OU-NORTH')].%s"; mockMvc.perform(get("/api/campaign/SIMPSONS2020X00/survey-units/contact-outcomes") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll(status().isOk(), checkJsonPath(ouJsonPath, "labelDem", "North region organizational unit"), @@ -914,7 +910,7 @@ void testGetContactOutcomeCountAllCampaign() throws Exception { String ouJsonPath = "$.[?(@.campaign.id == 'SIMPSONS2020X00')].%s"; mockMvc.perform(get("/api/campaigns/survey-units/contact-outcomes") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll(status().isOk(), checkJsonPath(ouJsonPath, "campaign.label", "Survey on the Simpsons tv show 2020"), @@ -941,7 +937,7 @@ void testGetContactOutcomeCountAllCampaign() throws Exception { @Order(21) void testGetNbSuAbandonedNotFound() throws Exception { mockMvc.perform(get("/api/campaign/test/survey-units/abandoned") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -955,7 +951,7 @@ void testGetNbSuAbandonedNotFound() throws Exception { @Order(22) void testGetNbSuNotAttributed() throws Exception { mockMvc.perform(get("/api/campaign/SIMPSONS2020X00/survey-units/not-attributed") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll(status().isOk(), jsonPath("$.count").value("0")); @@ -971,7 +967,7 @@ void testGetNbSuNotAttributed() throws Exception { @Order(23) void testGetNbSuNotAttributedNotFound() throws Exception { mockMvc.perform(get("/api/campaign/test/survey-units/not-attributed") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -998,7 +994,7 @@ void testPutVisibilityModifyAllDates() throws Exception { """; mockMvc.perform(put("/api/campaign/SIMPSONS2020X00/organizational-unit/OU-NORTH/visibility") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON) .content(campaignInput)) .andExpect(status().isOk()); @@ -1031,7 +1027,7 @@ void testPutVisibilityModifyCollectionStartDate() String jsonContent = String.format("{\"collectionStartDate\": %d}", now); mockMvc.perform(put("/api/campaign/SIMPSONS2020X00/organizational-unit/OU-NORTH/visibility") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON) .content(jsonContent)) .andExpect(status().isOk()); @@ -1059,7 +1055,7 @@ void testPutVisibilityModifyCollectionEndDate() String jsonContent = String.format("{\"collectionEndDate\": %d}", now); mockMvc.perform(put("/api/campaign/SIMPSONS2020X00/organizational-unit/OU-NORTH/visibility") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON) .content(jsonContent)) .andExpect(status().isOk()); @@ -1080,7 +1076,7 @@ void testPutVisibilityModifyCollectionEndDate() @Order(32) void testPutVisibilityEmptyBody() throws Exception { mockMvc.perform(put("/api/campaign/SIMPSONS2020X00/organizational-unit/OU-NORTH/visibility") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON) .content("{}")) .andExpect(status().isBadRequest()); @@ -1108,7 +1104,7 @@ void testPutVisibilityBadFormat() throws Exception { }"""; mockMvc.perform(put("/api/campaign/SIMPSONS2020X00/organizational-unit/OU-NORTH/visibility") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON) .content(requestBody)) .andExpect(status().isBadRequest()); @@ -1128,7 +1124,7 @@ void testPostMessage() throws Exception { message.setSender("abc"); mockMvc.perform(post("/api/message") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(message))) .andExpect(status().isOk()); @@ -1148,7 +1144,7 @@ void testPostMessage() throws Exception { @Order(35) void testPostMessageBadFormat() throws Exception { mockMvc.perform(post("/api/message") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(null))) .andExpect(status().isBadRequest()); @@ -1220,7 +1216,7 @@ void testPutMessageAsDelete() throws Exception { String url = String.format("/api/message/%d/interviewer/INTW1/delete", messageId); mockMvc.perform(put(url) - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); @@ -1241,7 +1237,7 @@ void testPutMessageAsReadWrongId() throws Exception { String url = String.format("/api/message/%d/interviewer/Test/read", messageId); mockMvc.perform(put(url) - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); @@ -1257,7 +1253,7 @@ void testPutMessageAsReadWrongId() throws Exception { @Order(41) void testGetMessageHistory() throws Exception { mockMvc.perform(get("/api/message-history") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll(status().isOk(), jsonPath("$[?(@.text == 'TEST')]").exists()); @@ -1276,7 +1272,7 @@ void testPostVerifyName() throws Exception { WsText message = new WsText("simps"); mockMvc.perform(post("/api/verify-name") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(message))) .andExpectAll(status().isOk(), @@ -1315,7 +1311,7 @@ void testGetInterviewer() throws Exception { String interviewerJsonPath = "$.[?(@.id == 'INTW1')].%s"; mockMvc.perform(get("/api/interviewers") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), @@ -1335,7 +1331,7 @@ void testGetInterviewer() throws Exception { @Order(45) void testGetInterviewerRelatedCampaigns() throws Exception { MvcResult result = mockMvc.perform(get("/api/interviewer/INTW1/campaigns") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), @@ -1361,7 +1357,7 @@ void testGetInterviewerRelatedCampaigns() throws Exception { @Order(46) void testGetInterviewerNotExistForCampaign() throws Exception { mockMvc.perform(get("/api/interviewer/INTW123/campaigns") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -1408,7 +1404,7 @@ void testGetSUClosable() throws Exception { mockMvc .perform(get("/api/survey-units/closable") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), @@ -1437,7 +1433,7 @@ void testGetSUClosable() throws Exception { void testGetContactOutcomeCountByCampaignAndInterviewer() throws Exception { mockMvc.perform(get("/api/campaign/SIMPSONS2020X00/survey-units/interviewer/INTW1/contact-outcomes") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), @@ -1466,7 +1462,7 @@ void testGetContactOutcomeCountByCampaignAndInterviewer() void testGetContactOutcomeCountByCampaignNotExistAndInterviewer() throws Exception { mockMvc.perform(get("/api/campaign/SIMPSONS2020X000000/survey-units/interviewer/INTW1/contact-outcomes") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isNotFound()); @@ -1485,7 +1481,7 @@ void testGetContactOutcomeCountByCampaignNotExistAndInterviewer() void testGetContactOutcomeCountByCampaignAndInterviewerNotExist() throws Exception { mockMvc.perform(get("/api/campaign/SIMPSONS2020X000000/survey-units/interviewer/INTW123/contact-outcomes") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isNotFound()); @@ -1504,7 +1500,7 @@ void testGetContactOutcomeCountByCampaignNotExist() throws Exception { mockMvc.perform(get("/api/campaign/SIMPSONS2020X000000/survey-units/contact-outcomes") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isNotFound()); @@ -1522,7 +1518,7 @@ void testPutCommentOnSu() throws Exception { String comment = asJsonString(new CommentDto(CommentType.MANAGEMENT, "Test of comment")); mockMvc.perform(put("/api/survey-unit/11/comment") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON) .content(comment)) .andExpect(status().isOk()); @@ -1550,7 +1546,7 @@ void testPutCommentSuNotExist() throws Exception { String comment = asJsonString(new CommentDto(CommentType.MANAGEMENT, "Test of comment")); mockMvc.perform(put("/api/survey-unit/11111111111/comment") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON) .content(comment)) .andExpect(status().isNotFound()); @@ -1567,7 +1563,7 @@ void testPutCommentSuNotExist() throws Exception { @Order(56) void testPutSuViewed() throws Exception { mockMvc.perform(put("/api/survey-unit/24/viewed") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); @@ -1586,7 +1582,7 @@ void testPutSuViewed() throws Exception { @Order(57) void testPutSuViewedNotExist() throws Exception { mockMvc.perform(put("/api/survey-unit/11111111111/viewed") - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .contentType(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -1602,7 +1598,7 @@ void testPutSuViewedNotExist() throws Exception { @Order(58) void testGetOrganizationUnits() throws Exception { mockMvc.perform(get("/api/organization-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), @@ -1635,7 +1631,7 @@ void testPostCampaignContext() throws Exception { campDto.setVisibilities(List.of(visi1, visi2)); mockMvc.perform(post(Constants.API_CAMPAIGN) - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(campDto))) .andExpect(status().isOk()); @@ -1692,7 +1688,7 @@ void testPostCampaignContextNoLabel() throws Exception { campDto.setVisibilities(List.of(visi1, visi2)); mockMvc.perform(post(Constants.API_CAMPAIGN) - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(campDto))) .andExpect(status().isBadRequest()); @@ -1723,7 +1719,7 @@ void testPostCampaignContextMissingOU() throws Exception { campDto.setVisibilities(List.of(visi1, visi2)); mockMvc.perform(post(Constants.API_CAMPAIGN) - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(campDto))) .andExpect(status().isBadRequest()); @@ -1758,7 +1754,7 @@ void testPostOrganizationUnitContext() throws Exception { ou2.setUsers(List.of(user3, user4)); mockMvc.perform(post("/api/organization-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(ou1, ou2)))) .andExpect(status().isOk()); @@ -1816,7 +1812,7 @@ void testPostOrganizationUnitContextDuplicateUser() OrganizationUnitType.LOCAL, List.of(user2, user3)); mockMvc.perform(post("/api/organization-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(ou1, ou2)))) .andExpect(status().isBadRequest()); @@ -1851,7 +1847,7 @@ void testPostOrganizationUnitContextNoOU() throws Exception { OrganizationUnitType.LOCAL, List.of(user2, user3)); mockMvc.perform(post("/api/organization-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(ou1, ou2)))) .andExpect(status().isBadRequest()); @@ -1877,7 +1873,7 @@ void testPostInterviewers() throws Exception { InterviewerContextDto interv2 = generateInterviewerBContextDto("INTERV2"); mockMvc.perform(post("/api/interviewers") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(interv1, interv2)))) .andExpect(status().isOk()); @@ -1917,7 +1913,7 @@ void testPostInterviewersMissingEmail() throws Exception { interv2.setEmail(null); mockMvc.perform(post("/api/interviewers") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(interv1, interv2)))) .andExpect(status().isBadRequest()); @@ -1943,7 +1939,7 @@ void testPostInterviewersDuplicateId() throws Exception { InterviewerContextDto interv2 = generateInterviewerBContextDto("INTERV3"); mockMvc.perform(post("/api/interviewers") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(interv1, interv2)))) .andExpect(status().isBadRequest()); @@ -1968,7 +1964,7 @@ void testPostInterviewersWithNoTitle() throws Exception { intervNoTitle.setTitle(null); mockMvc.perform(post("/api/interviewers") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(intervNoTitle)))) .andExpect(status().isOk()); @@ -1992,7 +1988,7 @@ void testPostInterviewersWithNoTitle() throws Exception { @Order(111) void testPostSurveyUnits() throws Exception { mockMvc.perform(post("/api/survey-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(generateSurveyUnit("8"))))) .andExpect(status().isOk()); @@ -2012,7 +2008,7 @@ void testPostSurveyUnits() throws Exception { @Order(112) void testPostSurveyUnitsDuplicateInDB() throws Exception { mockMvc.perform(post("/api/survey-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(generateSurveyUnit("8"))))) .andExpect(status().isBadRequest()); @@ -2032,7 +2028,7 @@ void testPostSurveyUnitsDuplicateInBody() throws Exception { SurveyUnitContextDto su = generateSurveyUnit("9"); mockMvc.perform(post("/api/survey-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(su, su)))) .andExpect(status().isBadRequest()); @@ -2054,7 +2050,7 @@ void testPostSurveyUnitsOUNotExist() throws Exception { su.setOrganizationUnitId("OU-TEST"); mockMvc.perform(post("/api/survey-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(su)))) .andExpect(status().isBadRequest()); @@ -2075,7 +2071,7 @@ void testPostSurveyUnitsCampaignNotExist() throws Exception { su.setCampaign("campaignTest"); mockMvc.perform(post("/api/survey-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(su)))) .andExpect(status().isBadRequest()); @@ -2097,7 +2093,7 @@ void testPostSurveyUnitsSUNotValid() throws Exception { // ID null mockMvc.perform(post("/api/survey-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(su)))) .andExpect(status().isBadRequest()); @@ -2106,7 +2102,7 @@ void testPostSurveyUnitsSUNotValid() throws Exception { su.setId("9"); su.setCampaign(""); mockMvc.perform(post("/api/survey-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(su)))) .andExpect(status().isBadRequest()); @@ -2115,7 +2111,7 @@ void testPostSurveyUnitsSUNotValid() throws Exception { su.setPersons(Collections.emptyList()); su.setCampaign("SIMPSONS2020X00"); mockMvc.perform(post("/api/survey-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(su)))) .andExpect(status().isBadRequest()); @@ -2140,7 +2136,7 @@ void testPostAssignements() throws Exception { SurveyUnitInterviewerLinkDto assign2 = new SurveyUnitInterviewerLinkDto("102", "INTW3"); mockMvc.perform(post(Constants.API_SURVEYUNITS_INTERVIEWERS) - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(assign1, assign2)))) .andDo(print()) @@ -2176,7 +2172,7 @@ void testPostAssignementsNoInterviewerDoesntExist() SurveyUnitInterviewerLinkDto assign2 = new SurveyUnitInterviewerLinkDto("104", "INTWDOESNTEXIST"); mockMvc.perform(post(Constants.API_SURVEYUNITS_INTERVIEWERS) - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(assign1, assign2)))) .andDo(print()) @@ -2206,7 +2202,7 @@ void testPostAssignementsNoInterviewerDoesntExist() @Order(120) void testPostUsersByOU() throws Exception { mockMvc.perform(post("/api/organization-unit/OU-NORTH/users") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of( new UserContextDto("TEST", "test", "test", null, null), @@ -2235,7 +2231,7 @@ void testPostUsersByOU() throws Exception { @Order(121) void testPostUsersByOUThatDoesNotExist() throws Exception { mockMvc.perform(post("/api/organization-unit/OU-TEST/users") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of( new UserContextDto("TEST", "test", "test", null, null), @@ -2256,7 +2252,7 @@ void testPostUsersByOUThatDoesNotExist() throws Exception { @Order(200) void testDeleteSurveyUnit() throws Exception { mockMvc.perform(delete("/api/survey-unit/11") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); @@ -2267,7 +2263,7 @@ void testDeleteSurveyUnit() throws Exception { @Order(201) void testDeleteSurveyUnitNotExist() throws Exception { mockMvc.perform(delete("/api/survey-unit/toto") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -2276,24 +2272,24 @@ void testDeleteSurveyUnitNotExist() throws Exception { @Order(202) void testDeleteCampaign() throws Exception { mockMvc.perform(delete("/api/campaign/XCLOSEDX00") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); assertTrue(campaignRepository.findById("XCLOSEDX00").isEmpty()); mockMvc.perform(delete("/api/campaign/SIMPSONS2020X00") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isConflict()); mockMvc.perform(delete("/api/campaign/SIMPSONS2020X00?force=false") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isConflict()); mockMvc.perform(delete("/api/campaign/SIMPSONS2020X00?force=true") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); @@ -2304,7 +2300,7 @@ void testDeleteCampaign() throws Exception { @Order(203) void testDeleteCampaignNotExist() throws Exception { mockMvc.perform(delete("/api/campaign/SIMPSONS2020XTT") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -2313,7 +2309,7 @@ void testDeleteCampaignNotExist() throws Exception { @Order(204) void testDeleteUser() throws Exception { mockMvc.perform(delete("/api/user/JKL") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); @@ -2324,7 +2320,7 @@ void testDeleteUser() throws Exception { @Order(205) void testDeleteUserNotExist() throws Exception { mockMvc.perform(delete("/api/user/USER") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -2345,7 +2341,7 @@ void testDeleteOrganizationUnit() throws Exception { }); mockMvc.perform(delete("/api/organization-unit/OU-NORTH") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isOk()); @@ -2356,7 +2352,7 @@ void testDeleteOrganizationUnit() throws Exception { @Order(207) void testDeleteOrganizationUnitWithUsersOrSurveyUnits() throws Exception { mockMvc.perform(delete("/api/organization-unit/OU-SOUTH") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isBadRequest()); } @@ -2365,7 +2361,7 @@ void testDeleteOrganizationUnitWithUsersOrSurveyUnits() throws Exception { @Order(208) void testDeleteOrganizationUnitNotExist() throws Exception { mockMvc.perform(delete("/api/organization-unit/TEST") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -2374,7 +2370,7 @@ void testDeleteOrganizationUnitNotExist() throws Exception { @Order(209) void testCreateValidUser() throws Exception { mockMvc.perform(post("/api/user") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(generateValidUser()))) .andExpect(status().isCreated()); @@ -2384,7 +2380,7 @@ void testCreateValidUser() throws Exception { @Order(210) void testCreateAreadyPresentUser() throws Exception { mockMvc.perform(post("/api/user") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(generateValidUser()))) .andExpect(status().isConflict()); @@ -2395,7 +2391,7 @@ void testCreateAreadyPresentUser() throws Exception { void testCreateInvalidUser() throws Exception { // Null user object mockMvc.perform(post("/api/user") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(null))) .andDo(print()) @@ -2405,7 +2401,7 @@ void testCreateInvalidUser() throws Exception { UserDto user = generateValidUser(); user.setFirstName(null); mockMvc.perform(post("/api/user") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(user))) .andExpect(status().isBadRequest()); @@ -2414,7 +2410,7 @@ void testCreateInvalidUser() throws Exception { user = generateValidUser(); user.setLastName(null); mockMvc.perform(post("/api/user") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(user))) .andExpect(status().isBadRequest()); @@ -2423,7 +2419,7 @@ void testCreateInvalidUser() throws Exception { user = generateValidUser(); user.setId(null); mockMvc.perform(post("/api/user") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(user))) .andExpect(status().isBadRequest()); @@ -2432,7 +2428,7 @@ void testCreateInvalidUser() throws Exception { user = generateValidUser(); user.getOrganizationUnit().setId("WHERE_IS_CHARLIE"); mockMvc.perform(post("/api/user") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(user))) .andExpect(status().isBadRequest()); @@ -2442,7 +2438,7 @@ void testCreateInvalidUser() throws Exception { @Order(212) void testUpdateMissingUser() throws Exception { mockMvc.perform(put("/api/user/TEST") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(generateValidUser()))) .andExpect(status().isNotFound()); @@ -2452,7 +2448,7 @@ void testUpdateMissingUser() throws Exception { @Order(213) void testUpdateWrongUser() throws Exception { mockMvc.perform(put("/api/user/GHI") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(generateValidUser()))) .andExpect(status().isConflict()); @@ -2465,7 +2461,7 @@ void testUpdateUser() throws Exception { user.setId("GHI"); mockMvc.perform(put("/api/user/GHI") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(user))) .andExpectAll( @@ -2481,7 +2477,7 @@ void testUpdateUser() throws Exception { @Order(215) void testAssignUser() throws Exception { mockMvc.perform(put("/api/user/GHI/organization-unit/OU-SOUTH") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), @@ -2494,7 +2490,7 @@ void testAssignUser() throws Exception { @Order(216) void testAssignUserMissingUser() throws Exception { mockMvc.perform(put("/api/user/MISSING/organization-unit/OU-SOUTH") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -2503,7 +2499,7 @@ void testAssignUserMissingUser() throws Exception { @Order(217) void testAssignUserMissingOu() throws Exception { mockMvc.perform(put("/api/user/GHI/organization-unit/MISSING") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -2512,14 +2508,14 @@ void testAssignUserMissingOu() throws Exception { @Order(218) void testOngoing() throws Exception { mockMvc.perform(get("/campaigns/ZCLOSEDX00/ongoing") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), jsonPath("$.ongoing").value(false)); mockMvc.perform(get("/campaigns/VQS2021X00/ongoing") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), @@ -2530,7 +2526,7 @@ void testOngoing() throws Exception { @Order(219) void testOngoingNotFound() throws Exception { mockMvc.perform(get("/campaigns/MISSING/ongoing") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .accept(MediaType.APPLICATION_JSON)) .andExpect(status().isNotFound()); } @@ -2561,7 +2557,7 @@ void testPutCampaign() throws Exception { // path variable campaignId not found in DB mockMvc.perform(put("/api/campaign/MISSING") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(campaignContext))) .andExpect(status().isNotFound()); @@ -2569,21 +2565,21 @@ void testPutCampaign() throws Exception { // BAD REQUESTS campaignContext.setCampaignLabel(null); mockMvc.perform(put("/api/campaign/ZCLOSEDX00") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(campaignContext))) .andExpect(status().isBadRequest()); campaignContext.setCampaignLabel(" "); mockMvc.perform(put("/api/campaign/ZCLOSEDX00") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(campaignContext))) .andExpect(status().isBadRequest()); campaignContext.setCampaignLabel(""); mockMvc.perform(put("/api/campaign/ZCLOSEDX00") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(campaignContext))) .andExpect(status().isBadRequest()); @@ -2591,7 +2587,7 @@ void testPutCampaign() throws Exception { campaignContext.setCampaignLabel("Everyday life and health survey 2021"); campaignContext.setVisibilities(List.of(emptyVcd)); mockMvc.perform(put("/api/campaign/ZCLOSEDX00") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(campaignContext))) .andExpect(status().isBadRequest()); @@ -2599,7 +2595,7 @@ void testPutCampaign() throws Exception { // NOT FOUND VISIBILITY campaignContext.setVisibilities(List.of(missingVcd)); mockMvc.perform(put("/api/campaign/ZCLOSEDX00") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(campaignContext))) .andExpect(status().isNotFound()); @@ -2607,7 +2603,7 @@ void testPutCampaign() throws Exception { // CONFLICT due to visibilities campaignContext.setVisibilities(List.of(invalidVcd)); mockMvc.perform(put("/api/campaign/ZCLOSEDX00") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(campaignContext))) .andExpect(status().isConflict()); @@ -2620,7 +2616,7 @@ void testPutCampaign() throws Exception { campaignContext.setIdentificationConfiguration(IdentificationConfiguration.NOIDENT); mockMvc.perform(put("/api/campaign/ZCLOSEDX00") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(campaignContext))) .andExpect(status().isOk()); @@ -2664,7 +2660,7 @@ void testUpdateVisibilityByOu() throws Exception { private ResultActions updateVisibility(String campaignId, String OuId, String visibility) throws Exception { return mockMvc.perform( put(updateVisibilityUrl(campaignId, OuId)) - .with(authentication(MANAGER)) + .with(authentication(LOCAL_USER)) .content(visibility) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON)); @@ -2762,7 +2758,7 @@ private UserDto generateValidUser() { private void addUnattributedSU(String suId) throws Exception { mockMvc.perform(post("/api/survey-units") - .with(authentication(MANAGER)) + .with(authentication(ADMIN)) .contentType(MediaType.APPLICATION_JSON) .content(asJsonString(List.of(generateSurveyUnit(suId))))); } diff --git a/src/test/java/fr/insee/pearljam/api/controller/CampaignControllerTest.java b/src/test/java/fr/insee/pearljam/api/controller/CampaignControllerTest.java index 1d2a1fd7..95b7c3b3 100644 --- a/src/test/java/fr/insee/pearljam/api/controller/CampaignControllerTest.java +++ b/src/test/java/fr/insee/pearljam/api/controller/CampaignControllerTest.java @@ -1,13 +1,14 @@ package fr.insee.pearljam.api.controller; +import fr.insee.pearljam.api.domain.Campaign; +import fr.insee.pearljam.api.utils.AuthenticatedUserTestHelper; +import fr.insee.pearljam.api.utils.dummy.AuthenticationUserFakeService; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; import fr.insee.pearljam.api.service.dummy.CampaignFakeService; import fr.insee.pearljam.api.service.dummy.ReferentFakeService; -import static fr.insee.pearljam.api.utils.AuthenticatedUserTestHelper.*; -import fr.insee.pearljam.api.utils.dummy.AuthenticationFakeHelper; import static org.assertj.core.api.Assertions.assertThat; @@ -16,20 +17,21 @@ class CampaignControllerTest { private CampaignController campaignController; private CampaignFakeService campaignService; private ReferentFakeService referentService; - private AuthenticationFakeHelper authenticationHelper; + private AuthenticationUserFakeService authenticatedUserService; @BeforeEach public void init() { - authenticationHelper = new AuthenticationFakeHelper(); - campaignService = new CampaignFakeService(); + Campaign campaign = new Campaign(); + campaignService = new CampaignFakeService(campaign); referentService = new ReferentFakeService(); + authenticatedUserService = new AuthenticationUserFakeService(AuthenticatedUserTestHelper.AUTH_ADMIN); + campaignController = new CampaignController(campaignService, referentService, authenticatedUserService); } @Test @DisplayName("On deletion, when force is true, deletion is done") void testDeletion() { - campaignController = new CampaignController(campaignService, authenticationHelper, referentService); - campaignController.deleteCampaignById(AUTH_MANAGER, "test", true); + campaignController.deleteCampaignById( "test", true); assertThat(campaignService.isDeleted()).isTrue(); } } diff --git a/src/test/java/fr/insee/pearljam/api/noAuth/TestNoAuth.java b/src/test/java/fr/insee/pearljam/api/noAuth/TestNoAuth.java index c4037a23..aa15d405 100644 --- a/src/test/java/fr/insee/pearljam/api/noAuth/TestNoAuth.java +++ b/src/test/java/fr/insee/pearljam/api/noAuth/TestNoAuth.java @@ -1,21 +1,23 @@ package fr.insee.pearljam.api.noAuth; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors.authentication; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; +import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import java.text.ParseException; +import java.time.Instant; import java.time.LocalDate; +import java.time.ZoneId; import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.List; import com.jayway.jsonpath.JsonPath; +import fr.insee.pearljam.api.service.DataSetInjectorService; import org.json.JSONException; import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.MethodOrderer; import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; @@ -36,13 +38,11 @@ import fr.insee.pearljam.api.dto.message.MessageDto; import fr.insee.pearljam.api.repository.ClosingCauseRepository; import fr.insee.pearljam.api.repository.MessageRepository; -import fr.insee.pearljam.api.utils.AuthenticatedUserTestHelper; import lombok.RequiredArgsConstructor; import org.springframework.test.web.servlet.ResultMatcher; /* Test class for no Authentication */ -@ActiveProfiles("test") -@Disabled("Refactor : migrate to mockMvc before enabling again") +@ActiveProfiles("noauth") @AutoConfigureMockMvc @ContextConfiguration @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) @@ -54,11 +54,11 @@ class TestNoAuth { private final MessageRepository messageRepository; private final ClosingCauseRepository closingCauseRepository; private final MockMvc mockMvc; + private final DataSetInjectorService injectorService; @BeforeEach - public void clearDataSet() throws Exception { - mockMvc.perform(delete("/api/delete-dataset").accept(MediaType.APPLICATION_JSON) - .with(authentication(AuthenticatedUserTestHelper.AUTH_MANAGER))); + public void clearDataSet() { + injectorService.deleteDataSet(); } /** @@ -68,33 +68,32 @@ public void clearDataSet() throws Exception { * */ @BeforeEach - public void initDataSetIfNotPresent() throws Exception { - mockMvc.perform(post("/api/create-dataset").accept(MediaType.APPLICATION_JSON) - .with(authentication(AuthenticatedUserTestHelper.AUTH_MANAGER))); + public void initDataSetIfNotPresent() { + injectorService.createDataSet(); } private ResultMatcher expectValidManagementStartDate() { - return expectTimestampFromCurrentDate("$.managementStartDate", -4, ChronoUnit.DAYS); + return expectTimestampFromCurrentDate("$[0].managementStartDate", -4, ChronoUnit.DAYS); } private ResultMatcher expectValidInterviewerStartDate() { - return expectTimestampFromCurrentDate("$.interviewerStartDate", -3, ChronoUnit.DAYS); + return expectTimestampFromCurrentDate("$[0].interviewerStartDate", -3, ChronoUnit.DAYS); } private ResultMatcher expectValidIdentificationPhaseStartDate() { - return expectTimestampFromCurrentDate("$.identificationPhaseStartDate", -2, ChronoUnit.DAYS); + return expectTimestampFromCurrentDate("$[0].identificationPhaseStartDate", -2, ChronoUnit.DAYS); } private ResultMatcher expectValidCollectionStartDate() { - return expectTimestampFromCurrentDate("$.collectionStartDate", -2, ChronoUnit.DAYS); + return expectTimestampFromCurrentDate("$[0].collectionStartDate", -1, ChronoUnit.DAYS); } private ResultMatcher expectValidCollectionEndDate() { - return expectTimestampFromCurrentDate("$.collectionEndDate", 1, ChronoUnit.MONTHS); + return expectTimestampFromCurrentDate("$[0].collectionEndDate", 1, ChronoUnit.MONTHS); } private ResultMatcher expectValidEndDate() { - return expectTimestampFromCurrentDate("$ndDate", 2, ChronoUnit.MONTHS); + return expectTimestampFromCurrentDate("$[0].endDate", 2, ChronoUnit.MONTHS); } private ResultMatcher expectTimestampFromCurrentDate(String expression, int unitToAdd, ChronoUnit chronoUnit) { @@ -102,7 +101,8 @@ private ResultMatcher expectTimestampFromCurrentDate(String expression, int unit String content = mvcResult.getResponse().getContentAsString(); long timestamp = JsonPath.read(content, expression); LocalDate localDateNow = LocalDate.now(); - LocalDate dateToCheck = LocalDate.ofEpochDay(timestamp); + Instant instant = Instant.ofEpochMilli(timestamp); + LocalDate dateToCheck = LocalDate.ofInstant(instant, ZoneId.systemDefault()); assertEquals(dateToCheck, localDateNow.plus(unitToAdd, chronoUnit)); }; } @@ -121,19 +121,19 @@ private ResultMatcher expectTimestampFromCurrentDate(String expression, int unit @Test @Order(1) void testGetCampaign() throws Exception { - mockMvc.perform(get("/api/campaigns").accept(MediaType.APPLICATION_JSON)) + mockMvc.perform(get("/api/campaigns") + .accept(MediaType.APPLICATION_JSON)) .andExpectAll( status().isOk(), - jsonPath("$.id").value("SIMPSONS2020X00"), - jsonPath("$.label").value("Survey on the Simpsons tv show 2020"), - jsonPath("$.allocated").value(4), - jsonPath("$.toAffect").value(0), - jsonPath("$.toFollowUp").value(0), - jsonPath("$.toReview").value(0), - jsonPath("$.finalized").value(0), - jsonPath("$.toProcessInterviewer").value(0), - jsonPath("$.preference").value(true), - jsonPath("$.managementStartDate").value(true), + jsonPath("$[0].id").value("SIMPSONS2020X00"), + jsonPath("$[0].label").value("Survey on the Simpsons tv show 2020"), + jsonPath("$[0].allocated").value(4), + jsonPath("$[0].toAffect").value(0), + jsonPath("$[0].toFollowUp").value(0), + jsonPath("$[0].toReview").value(3), + jsonPath("$[0].finalized").value(0), + jsonPath("$[0].toProcessInterviewer").value(0), + jsonPath("$[0].preference").value(true), expectValidManagementStartDate(), expectValidIdentificationPhaseStartDate(), expectValidInterviewerStartDate(), @@ -145,8 +145,9 @@ void testGetCampaign() throws Exception { @Test @Order(2) void testPutClosingCauseNoPreviousClosingCause() throws Exception { - mockMvc.perform(put("api/survey-unit/11/closing-cause/NPI") - .accept(MediaType.APPLICATION_JSON)) + mockMvc.perform(put("/api/survey-unit/11/closing-cause/NPI") + .accept(MediaType.APPLICATION_JSON)) + .andDo(print()) .andExpect(status().isOk()); List closingCauses = closingCauseRepository.findBySurveyUnitId("11"); @@ -167,9 +168,9 @@ void testPostMessage() throws Exception { MessageDto message = new MessageDto("TEST", recipients); message.setSender("GUEST"); mockMvc.perform(post("/api/message") - .accept(MediaType.APPLICATION_JSON) - .contentType(MediaType.APPLICATION_JSON) - .content(new ObjectMapper().writeValueAsString(message))) + .accept(MediaType.APPLICATION_JSON) + .contentType(MediaType.APPLICATION_JSON) + .content(new ObjectMapper().writeValueAsString(message))) .andExpect(status().isOk()); List messages = messageRepository diff --git a/src/test/java/fr/insee/pearljam/api/service/dummy/CampaignFakeService.java b/src/test/java/fr/insee/pearljam/api/service/dummy/CampaignFakeService.java index 5ad5b2d5..338ea549 100644 --- a/src/test/java/fr/insee/pearljam/api/service/dummy/CampaignFakeService.java +++ b/src/test/java/fr/insee/pearljam/api/service/dummy/CampaignFakeService.java @@ -3,6 +3,7 @@ import java.util.List; import java.util.Optional; +import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import fr.insee.pearljam.api.domain.Campaign; @@ -19,11 +20,14 @@ import fr.insee.pearljam.api.service.CampaignService; import lombok.Getter; -@Getter +@RequiredArgsConstructor public class CampaignFakeService implements CampaignService { + @Getter private boolean deleted = false; + private final Campaign campaign; + @Override public List getListCampaign(String userId) { // TODO Auto-generated method stub @@ -81,14 +85,12 @@ public Response postCampaign(CampaignContextDto campaignDto) @Override public Optional findById(String id) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'findById'"); + return Optional.of(campaign); } @Override public void delete(Campaign campaign) { - // TODO Auto-generated method stub - throw new UnsupportedOperationException("Unimplemented method 'delete'"); + deleted = true; } @Override diff --git a/src/test/java/fr/insee/pearljam/api/utils/AuthenticatedUserTestHelper.java b/src/test/java/fr/insee/pearljam/api/utils/AuthenticatedUserTestHelper.java index cc3da007..0382e0ac 100644 --- a/src/test/java/fr/insee/pearljam/api/utils/AuthenticatedUserTestHelper.java +++ b/src/test/java/fr/insee/pearljam/api/utils/AuthenticatedUserTestHelper.java @@ -1,7 +1,6 @@ package fr.insee.pearljam.api.utils; -import static fr.insee.pearljam.api.configuration.auth.AuthConstants.*; -import fr.insee.pearljam.api.configuration.auth.AuthorityRoleEnum; +import fr.insee.pearljam.domain.security.model.AuthorityRole; import org.springframework.security.authentication.AnonymousAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; @@ -17,15 +16,17 @@ public class AuthenticatedUserTestHelper { - public final static Authentication AUTH_MANAGER = getAuthenticatedUser("abc", - AuthorityRoleEnum.LOCAL_USER); + public final static Authentication AUTH_LOCAL_USER = getAuthenticatedUser("abc", + AuthorityRole.LOCAL_USER); public final static Authentication AUTH_INTERVIEWER = getAuthenticatedUser("INTW1", - AuthorityRoleEnum.INTERVIEWER); + AuthorityRole.INTERVIEWER); + public final static Authentication AUTH_ADMIN = getAuthenticatedUser("GUEST", + AuthorityRole.ADMIN); public final static Authentication NOT_AUTHENTICATED = getNotAuthenticatedUser(); - public static Authentication getAuthenticatedUser(String id, AuthorityRoleEnum... roles) { + public static Authentication getAuthenticatedUser(String id, AuthorityRole... roles) { List authorities = Stream.of(roles) - .map(role -> new SimpleGrantedAuthority(ROLE_PREFIX + role.name())).toList(); + .map(role -> new SimpleGrantedAuthority(role.securityRole())).toList(); Map headers = Map.of("typ", "JWT"); Map claims = Map.of( @@ -34,13 +35,13 @@ public static Authentication getAuthenticatedUser(String id, AuthorityRoleEnum.. "realmRoles", List.of("offline_access", "manager_local", "uma_authorization")); Jwt jwt = new Jwt("token-value", Instant.MIN, Instant.MAX, headers, claims); - return new JwtAuthenticationToken(jwt, authorities, "Jean Dupont"); + return new JwtAuthenticationToken(jwt, authorities, id); } private static Authentication getNotAuthenticatedUser() { Map principal = new HashMap<>(); Authentication auth = new AnonymousAuthenticationToken("id", principal, - List.of(new SimpleGrantedAuthority(ROLE_PREFIX + ANONYMOUS))); + List.of(new SimpleGrantedAuthority(AuthorityRole.ROLE_PREFIX + "ANONYMOUS"))); auth.setAuthenticated(false); return auth; } diff --git a/src/test/java/fr/insee/pearljam/api/utils/dummy/AuthenticationFakeHelper.java b/src/test/java/fr/insee/pearljam/api/utils/dummy/AuthenticationFakeHelper.java deleted file mode 100644 index dcc7ad9f..00000000 --- a/src/test/java/fr/insee/pearljam/api/utils/dummy/AuthenticationFakeHelper.java +++ /dev/null @@ -1,25 +0,0 @@ -package fr.insee.pearljam.api.utils.dummy; - -import fr.insee.pearljam.api.configuration.auth.AuthConstants; -import fr.insee.pearljam.api.web.authentication.AuthenticationHelper; -import org.springframework.security.core.Authentication; - -public class AuthenticationFakeHelper implements AuthenticationHelper { - @Override - public String getAuthToken(Authentication auth) { - return null; - } - - @Override - public String getUserId(Authentication authentication) { - if (authentication == null) { - return AuthConstants.GUEST; - } - return authentication.getName(); - } - - @Override - public Authentication getAuthenticationPrincipal() { - return null; - } -} diff --git a/src/test/java/fr/insee/pearljam/api/utils/dummy/AuthenticationUserFakeService.java b/src/test/java/fr/insee/pearljam/api/utils/dummy/AuthenticationUserFakeService.java new file mode 100644 index 00000000..a2e5a955 --- /dev/null +++ b/src/test/java/fr/insee/pearljam/api/utils/dummy/AuthenticationUserFakeService.java @@ -0,0 +1,26 @@ +package fr.insee.pearljam.api.utils.dummy; + +import fr.insee.pearljam.domain.security.model.AuthorityRole; +import fr.insee.pearljam.domain.security.port.userside.AuthenticatedUserService; +import lombok.RequiredArgsConstructor; +import org.springframework.security.core.Authentication; + +@RequiredArgsConstructor +public class AuthenticationUserFakeService implements AuthenticatedUserService { + private final Authentication authenticationUser; + + @Override + public String getCurrentUserId() { + return authenticationUser.getName(); + } + + @Override + public boolean hasRole(AuthorityRole role) { + return true; + } + + @Override + public boolean hasAnyRole(AuthorityRole... role) { + return true; + } +} diff --git a/src/test/java/fr/insee/pearljam/infrastructure/security/config/GrantedAuthorityConverterTest.java b/src/test/java/fr/insee/pearljam/infrastructure/security/config/GrantedAuthorityConverterTest.java new file mode 100644 index 00000000..b4495a33 --- /dev/null +++ b/src/test/java/fr/insee/pearljam/infrastructure/security/config/GrantedAuthorityConverterTest.java @@ -0,0 +1,100 @@ +package fr.insee.pearljam.infrastructure.security.config; + +import fr.insee.pearljam.api.configuration.properties.RoleProperties; +import fr.insee.pearljam.domain.security.model.AuthorityRole; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.oauth2.jwt.Jwt; + +import java.time.Instant; +import java.util.*; +import java.util.stream.Stream; + +import static org.assertj.core.api.Assertions.assertThat; + +class GrantedAuthorityConverterTest { + + private GrantedAuthorityConverter converter; + + private RoleProperties roleProperties; + + private static final String jwtRoleInterviewer = "interviewer"; + private static final String jwtRoleLocalUser = "localUser"; + private static final String jwtRoleNationalUser = "nationalUser"; + private static final String jwtRoleAdmin = "admin"; + private static final String jwtRoleWebclient = "webclient"; + + @BeforeEach + void init() { + roleProperties = new RoleProperties(jwtRoleInterviewer, jwtRoleLocalUser, jwtRoleNationalUser, jwtRoleAdmin, jwtRoleWebclient); + converter = new GrantedAuthorityConverter(roleProperties); + } + + @Test + @DisplayName("Given a JWT, when converting null or empty JWT role, then converting ignore these roles") + void testConverter01() { + List tokenRoles = new ArrayList<>(); + tokenRoles.add(null); + tokenRoles.add(""); + Jwt jwt = createJwt(tokenRoles); + Collection authorities = converter.convert(jwt); + assertThat(authorities).isEmpty(); + } + + @Test + @DisplayName("Given a JWT, when converting roles, then convert only JWT roles matching roles in role properties") + void testConverter02() { + + List tokenRoles = List.of("dummyRole1", roleProperties.local_user(), "dummyRole2", roleProperties.national_user(), "dummyRole3", roleProperties.interviewer()); + Jwt jwt = createJwt(tokenRoles); + + Collection authorities = converter.convert(jwt); + assertThat(authorities) + .hasSize(3) + .containsExactlyInAnyOrder( + new SimpleGrantedAuthority(AuthorityRole.INTERVIEWER.securityRole()), + new SimpleGrantedAuthority(AuthorityRole.LOCAL_USER.securityRole()), + new SimpleGrantedAuthority(AuthorityRole.NATIONAL_USER.securityRole())); + } + + @ParameterizedTest + @MethodSource("provideJWTRoleWithAppRoleAssociated") + @DisplayName("Given a JWT, when converting roles, then assure each JWT role is converted to equivalent app role") + void testConverter03(String jwtRole, AuthorityRole appRole) { + converter = new GrantedAuthorityConverter(roleProperties); + List tokenRoles = List.of(jwtRole); + Jwt jwt = createJwt(tokenRoles); + Collection authorities = converter.convert(jwt); + assertThat(authorities) + .hasSize(1) + .contains(new SimpleGrantedAuthority(AuthorityRole.ROLE_PREFIX + appRole)); + } + + private static Stream provideJWTRoleWithAppRoleAssociated() { + return Stream.of( + Arguments.of(jwtRoleInterviewer, AuthorityRole.INTERVIEWER), + Arguments.of(jwtRoleLocalUser, AuthorityRole.LOCAL_USER), + Arguments.of(jwtRoleNationalUser, AuthorityRole.NATIONAL_USER), + Arguments.of(jwtRoleAdmin, AuthorityRole.ADMIN), + Arguments.of(jwtRoleWebclient, AuthorityRole.WEBCLIENT)); + } + + private Jwt createJwt(List tokenRoles) { + Map jwtHeaders = new HashMap<>(); + jwtHeaders.put("header", "headerValue"); + + Map claims = new HashMap<>(); + Map> realmRoles = new HashMap<>(); + realmRoles.put(GrantedAuthorityConverter.REALM_ACCESS_ROLE, tokenRoles); + claims.put(GrantedAuthorityConverter.REALM_ACCESS, realmRoles); + + return new Jwt("user-id", Instant.now(), Instant.MAX, jwtHeaders, claims); + } +} + diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-auth.properties similarity index 78% rename from src/test/resources/application-test.properties rename to src/test/resources/application-auth.properties index 498e3113..c62869df 100644 --- a/src/test/resources/application-test.properties +++ b/src/test/resources/application-auth.properties @@ -21,12 +21,7 @@ logging.level.root=INFO logging.level.liquibase=WARN -keycloak.realm=insee-realm -keycloak.resource=client-web -keycloak.public-client=true -keycloak.bearer-only=true -keycloak.principal-attribute:preferred_username -keycloak.auth-server-url = localhost +feature.oidc.enabled=true #Datacollection config fr.insee.pearljam.datacollection.service.url.scheme=http @@ -42,7 +37,7 @@ fr.insee.pearljam.mail.service.url.login=pearljam fr.insee.pearljam.mail.service.url.password=pearljam # local database -spring.datasource.url=jdbc:h2:mem:testdb;NON_KEYWORDS=user,value;DATABASE_TO_UPPER=TRUE;DEFAULT_NULL_ORDERING=HIGH;INIT=create domain if not exists jsonb as json;MODE=PostgreSQL +spring.datasource.url=jdbc:h2:mem:testauthdb;NON_KEYWORDS=user,value;DATABASE_TO_UPPER=TRUE;DEFAULT_NULL_ORDERING=HIGH;INIT=create domain if not exists jsonb as json;MODE=PostgreSQL spring.datasource.driverClassName=org.h2.Driver spring.datasource.username=sa spring.datasource.password=password diff --git a/src/test/resources/application-noauth.properties b/src/test/resources/application-noauth.properties new file mode 100644 index 00000000..beb16123 --- /dev/null +++ b/src/test/resources/application-noauth.properties @@ -0,0 +1,46 @@ +spring.application.name=api +# spring.profiles.active=test + +application.auth=keycloak +application.corsOrigins='*' + +application.roles.interviewer=interviewer_access +application.roles.local_user=local_manager_access +application.roles.national_user=national_manager_access +application.roles.admin=admin_access +application.roles.webclient=webclient_access + +fr.insee.pearljam.application.guestOU=OU-POLE + +spring.liquibase.enabled=true +spring.liquibase.defaultSchema=public +spring.liquibase.contexts=test +spring.liquibase.changeLog=classpath:db/master.xml + +logging.level.root=INFO + +logging.level.liquibase=WARN + +feature.oidc.enabled=false + +#Datacollection config +fr.insee.pearljam.datacollection.service.url.scheme=http +fr.insee.pearljam.datacollection.service.url.host=localhost +fr.insee.pearljam.datacollection.service.url.port=8081 + +#Mail service config +fr.insee.pearljam.mail.service.url.scheme=http +fr.insee.pearljam.mail.service.url.host=localhost +fr.insee.pearljam.mail.service.url.port=8082 +fr.insee.pearljam.mail.service.recipients.list=pearl@pearljam.fr,jam@pearljam.fr +fr.insee.pearljam.mail.service.url.login=pearljam +fr.insee.pearljam.mail.service.url.password=pearljam + +# local database +spring.datasource.url=jdbc:h2:mem:testnoauthdb;NON_KEYWORDS=user,value;DATABASE_TO_UPPER=TRUE;DEFAULT_NULL_ORDERING=HIGH;INIT=create domain if not exists jsonb as json;MODE=PostgreSQL +spring.datasource.driverClassName=org.h2.Driver +spring.datasource.username=sa +spring.datasource.password=password + +# test verbosity +spring.test.mockmvc.print=none From 641e4ee285e7a8b4592ee5fd7d7ebab9cf5f76c2 Mon Sep 17 00:00:00 2001 From: davdarras Date: Wed, 19 Jun 2024 16:41:39 +0200 Subject: [PATCH 2/3] fix: remove useless check on user id --- .../api/controller/CampaignController.java | 52 ++-------- .../controller/ClosingCauseController.java | 25 ++--- .../controller/ContactOutcomeController.java | 67 +++++-------- .../api/controller/InterviewerController.java | 19 ---- .../api/controller/MessageController.java | 83 +++++----------- .../api/controller/PreferenceController.java | 12 +-- .../api/controller/StateController.java | 99 ++++++++----------- .../api/controller/SurveyUnitController.java | 48 --------- .../api/controller/UserController.java | 35 +++---- 9 files changed, 127 insertions(+), 313 deletions(-) diff --git a/src/main/java/fr/insee/pearljam/api/controller/CampaignController.java b/src/main/java/fr/insee/pearljam/api/controller/CampaignController.java index d5666e2d..15996f73 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/CampaignController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/CampaignController.java @@ -87,14 +87,9 @@ public ResponseEntity postCampaign(@RequestBody CampaignContextDto campa public ResponseEntity> getListCampaign() { String userId = authenticatedUserService.getCurrentUserId(); log.info("User {} : GET related campaigns", userId); - if (StringUtils.isBlank(userId)) { - log.warn(NO_USER_ID); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - List lstCampaigns = campaignService.getListCampaign(userId); - log.info("User {} -> {} related campaigns found", userId, lstCampaigns.size()); - return new ResponseEntity<>(lstCampaigns, HttpStatus.OK); - } + List lstCampaigns = campaignService.getListCampaign(userId); + log.info("User {} -> {} related campaigns found", userId, lstCampaigns.size()); + return new ResponseEntity<>(lstCampaigns, HttpStatus.OK); } /** @@ -109,15 +104,11 @@ public ResponseEntity> getListCampaign() { public ResponseEntity> getAllCampaigns() { String userId = authenticatedUserService.getCurrentUserId(); log.info("User {} : GET all campaigns", userId); - if (StringUtils.isBlank(userId)) { - log.warn(NO_USER_ID); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - List lstCampaigns = campaignService.getAllCampaigns(); - log.info("User {}, GET all campaigns ({} campaigns found) resulting in 200", userId, - lstCampaigns.size()); - return new ResponseEntity<>(lstCampaigns, HttpStatus.OK); - } + List lstCampaigns = campaignService.getAllCampaigns(); + log.info("User {}, GET all campaigns ({} campaigns found) resulting in 200", userId, + lstCampaigns.size()); + return new ResponseEntity<>(lstCampaigns, HttpStatus.OK); + } /** @@ -131,10 +122,6 @@ public ResponseEntity> getAllCampaigns() { @GetMapping(path = Constants.API_INTERVIEWER_CAMPAIGNS) public ResponseEntity> getInterviewerCampaigns() { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - log.warn(NO_USER_ID); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } log.info("Interviewer {} : GET related campaigns", userId); List lstCampaigns = campaignService.getInterviewerCampaigns(userId); log.info("Interviewer {} : returned {} campaigns, resulting in 200", userId, lstCampaigns.size()); @@ -155,10 +142,6 @@ public ResponseEntity> getInterviewerCampaigns() { @GetMapping(path = Constants.API_CAMPAIGN_ID_INTERVIEWERS) public ResponseEntity> getListInterviewers(@PathVariable(value = "id") String id) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - log.warn(NO_USER_ID); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } log.info("{} try to get campaign[{}] interviewers ", userId, id); List lstInterviewer; try { @@ -188,10 +171,6 @@ public ResponseEntity> getListInterviewers(@PathVariable(va @GetMapping(path = Constants.API_CAMPAIGN_ID_VISIBILITIES) public ResponseEntity> getVisibilities(@PathVariable(value = "id") String id) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - log.warn(NO_USER_ID); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } log.info("{} try to get campaign[{}] visibilities ", userId, id); if (!campaignService.findById(id).isPresent()) { log.warn("Can't find visibilities : campaign {} is missing", id); @@ -219,10 +198,6 @@ public ResponseEntity> getVisibilities(@PathVariable( @GetMapping(path = Constants.API_CAMPAIGN_ID_SU_ABANDONED) public ResponseEntity getNbSUAbandoned(@PathVariable(value = "id") String id) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - log.warn(NO_USER_ID); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } log.info("{} try to get campaign[{}] abandoned survey-units ", userId, id); CountDto nbSUAbandoned; try { @@ -249,10 +224,6 @@ public ResponseEntity getNbSUAbandoned(@PathVariable(value = "id") Str @GetMapping(path = Constants.API_CAMPAIGN_ID_SU_NOTATTRIBUTED) public ResponseEntity getNbSUNotAttributed(@PathVariable(value = "id") String id) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - log.warn(NO_USER_ID); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } log.info("{} try to get campaign[{}] not attributed survey-units ", userId, id); CountDto nbSUNotAttributed; try { @@ -280,10 +251,6 @@ public ResponseEntity putVisibilityDate( @PathVariable(value = "idCampaign") String idCampaign, @PathVariable(value = "idOu") String idOu) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - log.info(NO_USER_ID); - return new ResponseEntity<>(NO_USER_ID, HttpStatus.FORBIDDEN); - } log.info("{} try to change OU[{}] visibility on campaign[{}] ", userId, idOu, idCampaign); HttpStatus returnCode = campaignService.updateVisibility(idCampaign, idOu, visibilityUpdated); log.info("PUT visibility with CampaignId {} for Organizational Unit {} resulting in {}", idCampaign, @@ -337,9 +304,6 @@ public ResponseEntity putCampaign(@PathVariable(value = "id") String id, String userId = authenticatedUserService.getCurrentUserId(); log.info("{} try to update campaign {} collection dates", userId, id); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } HttpStatus returnCode = campaignService.updateCampaign(id, campaign); log.info("PUT campaign with id {} resulting in {}", id, returnCode.value()); return new ResponseEntity<>(returnCode); diff --git a/src/main/java/fr/insee/pearljam/api/controller/ClosingCauseController.java b/src/main/java/fr/insee/pearljam/api/controller/ClosingCauseController.java index 730b73d8..28192eb5 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/ClosingCauseController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/ClosingCauseController.java @@ -50,21 +50,16 @@ public ResponseEntity getClosingCauseCount( String userId = authenticatedUserService.getCurrentUserId(); List associatedOrgUnits = utilsService.getRelatedOrganizationUnits(userId); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - ClosingCauseCountDto closingCountDto; - try { - closingCountDto = closingCauseService.getClosingCauseCount(userId, id, idep, date, - associatedOrgUnits); - } catch (NotFoundException e) { - log.error(e.getMessage()); - log.info("Get ClosingCauseCount resulting in 404"); - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - log.info("Get ClosingCauseCount resulting in 200"); - return new ResponseEntity<>(closingCountDto, HttpStatus.OK); + ClosingCauseCountDto closingCountDto; + try { + closingCountDto = closingCauseService.getClosingCauseCount(userId, id, idep, date, + associatedOrgUnits); + } catch (NotFoundException e) { + log.error(e.getMessage()); + log.info("Get ClosingCauseCount resulting in 404"); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } - + log.info("Get ClosingCauseCount resulting in 200"); + return new ResponseEntity<>(closingCountDto, HttpStatus.OK); } } diff --git a/src/main/java/fr/insee/pearljam/api/controller/ContactOutcomeController.java b/src/main/java/fr/insee/pearljam/api/controller/ContactOutcomeController.java index f33151c5..8f1fa132 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/ContactOutcomeController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/ContactOutcomeController.java @@ -45,20 +45,17 @@ public class ContactOutcomeController { public ResponseEntity getNbSUNotAttributedContactOutcomes( @PathVariable(value = "id") String id, @RequestParam(required = false, name = "date") Long date) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - ContactOutcomeTypeCountDto contactOutcomes; - try { - contactOutcomes = contactOutcomeService.getNbSUNotAttributedContactOutcomes(userId, id, date); - } catch (NotFoundException e) { - log.error(e.getMessage()); - log.info("Get Contact-outcomes count for non attributted SUs resulting in 404"); - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - log.info("Get Contact-outcomes count for non attributted SUs resulting in 200"); - return new ResponseEntity<>(contactOutcomes, HttpStatus.OK); + ContactOutcomeTypeCountDto contactOutcomes; + try { + contactOutcomes = contactOutcomeService.getNbSUNotAttributedContactOutcomes(userId, id, date); + } catch (NotFoundException e) { + log.error(e.getMessage()); + log.info("Get Contact-outcomes count for non attributted SUs resulting in 404"); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } + log.info("Get Contact-outcomes count for non attributted SUs resulting in 200"); + return new ResponseEntity<>(contactOutcomes, HttpStatus.OK); + } /** @@ -75,18 +72,15 @@ public ResponseEntity getNbSUNotAttributedContactOut public ResponseEntity> getCampaignsContactOutcomeTypeCount( @RequestParam(required = false, name = "date") Long date) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - List listContactOutcomeTypeCountDto = contactOutcomeService - .getContactOutcomeTypeCountByCampaign(userId, date); - if (listContactOutcomeTypeCountDto == null) { - log.info("Get contactOutcomeTypeCount resulting in 404"); - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - log.info("Get contactOutcomeTypeCount resulting in 200"); - return new ResponseEntity<>(listContactOutcomeTypeCountDto, HttpStatus.OK); + + List listContactOutcomeTypeCountDto = contactOutcomeService + .getContactOutcomeTypeCountByCampaign(userId, date); + if (listContactOutcomeTypeCountDto == null) { + log.info("Get contactOutcomeTypeCount resulting in 404"); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } + log.info("Get contactOutcomeTypeCount resulting in 200"); + return new ResponseEntity<>(listContactOutcomeTypeCountDto, HttpStatus.OK); } /** @@ -104,20 +98,16 @@ public ResponseEntity> getCampaignsContactOutco public ResponseEntity getContactOutcomeTypeCountByCampaign( @PathVariable(value = "id") String id, @RequestParam(required = false, name = "date") Long date) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - ContactOutcomeTypeCountCampaignDto stateCountCampaignDto; - try { - stateCountCampaignDto = contactOutcomeService.getContactOutcomeCountTypeByCampaign(userId, id, date); - } catch (NotFoundException e) { - log.error(e.getMessage()); - log.info("Get contact-outcome type count resulting in 404"); - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - log.info("Get contact-outcome type count resulting in 200"); - return new ResponseEntity<>(stateCountCampaignDto, HttpStatus.OK); + ContactOutcomeTypeCountCampaignDto stateCountCampaignDto; + try { + stateCountCampaignDto = contactOutcomeService.getContactOutcomeCountTypeByCampaign(userId, id, date); + } catch (NotFoundException e) { + log.error(e.getMessage()); + log.info("Get contact-outcome type count resulting in 404"); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } + log.info("Get contact-outcome type count resulting in 200"); + return new ResponseEntity<>(stateCountCampaignDto, HttpStatus.OK); } /** @@ -135,9 +125,6 @@ public ResponseEntity getContactOuctomeByCampaignAnd @PathVariable(value = "id") String id, @PathVariable(value = "idep") String idep, @RequestParam(required = false, name = "date") Long date) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } ContactOutcomeTypeCountDto cotd; try { cotd = contactOutcomeService.getContactOutcomeByInterviewerAndCampaign(userId, id, idep, date); diff --git a/src/main/java/fr/insee/pearljam/api/controller/InterviewerController.java b/src/main/java/fr/insee/pearljam/api/controller/InterviewerController.java index 23a30b50..5ef447f1 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/InterviewerController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/InterviewerController.java @@ -68,9 +68,6 @@ public ResponseEntity postInterviewers(@RequestBody List> getListInterviewers() { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } Set lstInterviewer = interviewerService.getListInterviewers(userId); if (lstInterviewer == null) { log.info("Get interviewers resulting in 404"); @@ -85,10 +82,6 @@ public ResponseEntity> getListInterviewers() { @GetMapping(path = Constants.API_INTERVIEWER_ID) public ResponseEntity getInterviewer(@PathVariable(value = "id") String id) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - log.info("{} -> Get interviewer [{}] resulting in 403 : unknown user", userId, id); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } Optional interviewer = interviewerService.findDtoById(id); if (interviewer.isEmpty()) { log.info("{} -> Get interviewer [{}] resulting in 404", userId, id); @@ -103,9 +96,6 @@ public ResponseEntity getInterviewer(@PathVariable(value @GetMapping(path = Constants.API_ADMIN_INTERVIEWERS) public ResponseEntity> getCompleteListInterviewers() { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } List lstInterviewer = interviewerService.getCompleteListInterviewers(); if (lstInterviewer.isEmpty()) { log.info("{} -> Get all interviewers resulting in 404 : no interviewers", userId); @@ -120,9 +110,6 @@ public ResponseEntity> getCompleteListInterviewers() @GetMapping(path = Constants.API_INTERVIEWER_ID_CAMPAIGNS) public ResponseEntity> getListCampaigns(@PathVariable(value = "id") String id) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } Optional> list = interviewerService.findCampaignsOfInterviewer(id); if (!list.isPresent()) { log.info("{} -> Get interviewer campaigns resulting in 404", userId); @@ -139,8 +126,6 @@ public ResponseEntity updateInterviewer( @PathVariable(value = "id") String id, @RequestBody InterviewerContextDto interviewer) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) - return new ResponseEntity<>(HttpStatus.FORBIDDEN); if (id == null) return new ResponseEntity<>(HttpStatus.BAD_REQUEST); @@ -160,10 +145,6 @@ public ResponseEntity updateInterviewer( @DeleteMapping(path = Constants.API_INTERVIEWER_ID) public ResponseEntity deleteInterviewer(@PathVariable(value = "id") String id) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - log.warn("{} : DELETE interviewer with id {} resulting in 403.", userId, id); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } if (id == null) { log.warn("{} : no interviewerId provided : resulting in 400.", userId); diff --git a/src/main/java/fr/insee/pearljam/api/controller/MessageController.java b/src/main/java/fr/insee/pearljam/api/controller/MessageController.java index 578a9b5e..668481db 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/MessageController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/MessageController.java @@ -47,18 +47,15 @@ public class MessageController { @PostMapping(path = "/message") public ResponseEntity postMessage(@RequestBody MessageDto message) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - String text = message.getText(); - List recipients = message.getRecipients(); - log.info("POST text '{}' ", text); - for (String recipient : recipients) { - log.info("POST recipient '{}' ", recipient); - } - HttpStatus returnCode = messageService.addMessage(text, recipients, userId); - return new ResponseEntity<>(returnCode); + String text = message.getText(); + List recipients = message.getRecipients(); + log.info("POST text '{}' ", text); + for (String recipient : recipients) { + log.info("POST recipient '{}' ", recipient); } + HttpStatus returnCode = messageService.addMessage(text, recipients, userId); + return new ResponseEntity<>(returnCode); + } /** @@ -70,17 +67,12 @@ public ResponseEntity postMessage(@RequestBody MessageDto message) { public ResponseEntity postMessage( @PathVariable(value = "id") Long id, @PathVariable(value = "idep") String idep) { - String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - HttpStatus returnCode = messageService.markAsRead(id, idep); - if (returnCode == HttpStatus.OK) { - this.brokerMessagingTemplate.convertAndSend("/notifications/".concat(idep.toUpperCase()), - "new message"); - } - return new ResponseEntity<>(returnCode); + HttpStatus returnCode = messageService.markAsRead(id, idep); + if (returnCode == HttpStatus.OK) { + this.brokerMessagingTemplate.convertAndSend("/notifications/".concat(idep.toUpperCase()), + "new message"); } + return new ResponseEntity<>(returnCode); } /** @@ -92,17 +84,12 @@ public ResponseEntity postMessage( public ResponseEntity postDeletedMessage( @PathVariable(value = "id") Long id, @PathVariable(value = "idep") String idep) { - String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - HttpStatus returnCode = messageService.markAsDeleted(id, idep); - if (returnCode == HttpStatus.OK) { - this.brokerMessagingTemplate.convertAndSend("/notifications/".concat(idep.toUpperCase()), - "new message"); - } - return new ResponseEntity<>(returnCode); + HttpStatus returnCode = messageService.markAsDeleted(id, idep); + if (returnCode == HttpStatus.OK) { + this.brokerMessagingTemplate.convertAndSend("/notifications/".concat(idep.toUpperCase()), + "new message"); } + return new ResponseEntity<>(returnCode); } /** @@ -111,13 +98,8 @@ public ResponseEntity postDeletedMessage( @Operation(summary = "Get a message") @GetMapping(path = "/messages/{id}") public ResponseEntity> getMessages(@PathVariable(value = "id") String id) { - String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - List messages = messageService.getMessages(id); - return new ResponseEntity<>(messages, HttpStatus.OK); - } + List messages = messageService.getMessages(id); + return new ResponseEntity<>(messages, HttpStatus.OK); } /** @@ -127,12 +109,8 @@ public ResponseEntity> getMessages(@PathVariable(value = "id") @GetMapping(path = "/message-history") public ResponseEntity> getMessageHistory() { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - List messages = messageService.getMessageHistory(userId); - return new ResponseEntity<>(messages, HttpStatus.OK); - } + List messages = messageService.getMessageHistory(userId); + return new ResponseEntity<>(messages, HttpStatus.OK); } /** @@ -142,16 +120,12 @@ public ResponseEntity> getMessageHistory() { @PostMapping(path = "/verify-name") public ResponseEntity postMessage(@RequestBody WsText name) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - String text = name.getText(); - List resp = messageService.verifyName(text, userId); - if (resp != null) { - return new ResponseEntity<>(resp, HttpStatus.OK); - } - return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); + String text = name.getText(); + List resp = messageService.verifyName(text, userId); + if (resp != null) { + return new ResponseEntity<>(resp, HttpStatus.OK); } + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR); } /** @@ -161,9 +135,6 @@ public ResponseEntity postMessage(@RequestBody WsText name) { @PostMapping(path = "/mail") public ResponseEntity postMailMessage(@RequestBody MailDto mail) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } log.info("User {} send a mail", userId); HttpStatus returnCode = sendMail.apply(mail.getContent(), mail.getSubject()); return new ResponseEntity<>(returnCode); diff --git a/src/main/java/fr/insee/pearljam/api/controller/PreferenceController.java b/src/main/java/fr/insee/pearljam/api/controller/PreferenceController.java index 9ed6a149..8c022b53 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/PreferenceController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/PreferenceController.java @@ -37,13 +37,9 @@ public class PreferenceController { @PutMapping(path = "/preferences") public ResponseEntity updateSurveyUnit(@RequestBody List listPreference) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - HttpStatus returnCode = preferenceService.setPreferences(listPreference, userId); - log.info("PUT preferences '{}' for user {} resulting in {}", String.join(", ", listPreference), userId, - returnCode.value()); - return new ResponseEntity<>(returnCode); - } + HttpStatus returnCode = preferenceService.setPreferences(listPreference, userId); + log.info("PUT preferences '{}' for user {} resulting in {}", String.join(", ", listPreference), userId, + returnCode.value()); + return new ResponseEntity<>(returnCode); } } diff --git a/src/main/java/fr/insee/pearljam/api/controller/StateController.java b/src/main/java/fr/insee/pearljam/api/controller/StateController.java index 7816e1e5..6f14926d 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/StateController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/StateController.java @@ -51,21 +51,16 @@ public ResponseEntity getInterviewerStateCount( String userId = authenticatedUserService.getCurrentUserId(); List associatedOrgUnits = utilsService.getRelatedOrganizationUnits(userId); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - StateCountDto stateCountDto; - try { - stateCountDto = stateService.getStateCount(userId, id, idep, date, associatedOrgUnits); - } catch (NotFoundException e) { - log.error(e.getMessage()); - log.info("Get interviewerStateCount resulting in 404"); - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - log.info("Get interviewerStateCount resulting in 200"); - return new ResponseEntity<>(stateCountDto, HttpStatus.OK); + StateCountDto stateCountDto; + try { + stateCountDto = stateService.getStateCount(userId, id, idep, date, associatedOrgUnits); + } catch (NotFoundException e) { + log.error(e.getMessage()); + log.info("Get interviewerStateCount resulting in 404"); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } - + log.info("Get interviewerStateCount resulting in 200"); + return new ResponseEntity<>(stateCountDto, HttpStatus.OK); } /** @@ -82,20 +77,16 @@ public ResponseEntity getNbSUNotAttributedStateCount( @PathVariable(value = "id") String id, @RequestParam(required = false, name = "date") Long date) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - StateCountDto stateCountDto; - try { - stateCountDto = stateService.getNbSUNotAttributedStateCount(userId, id, date); - } catch (NotFoundException e) { - log.error(e.getMessage()); - log.info("Get state count for non attributted SUs resulting in 404"); - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - log.info("Get state count for non attributted SUs resulting in 200"); - return new ResponseEntity<>(stateCountDto, HttpStatus.OK); + StateCountDto stateCountDto; + try { + stateCountDto = stateService.getNbSUNotAttributedStateCount(userId, id, date); + } catch (NotFoundException e) { + log.error(e.getMessage()); + log.info("Get state count for non attributted SUs resulting in 404"); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } + log.info("Get state count for non attributted SUs resulting in 200"); + return new ResponseEntity<>(stateCountDto, HttpStatus.OK); } /** @@ -114,20 +105,16 @@ public ResponseEntity getCampaignStateCount( @PathVariable(value = "id") String id, @RequestParam(required = false, name = "date") Long date) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - StateCountCampaignDto stateCountCampaignDto; - try { - stateCountCampaignDto = stateService.getStateCountByCampaign(userId, id, date); - } catch (NotFoundException e) { - log.error(e.getMessage()); - log.info("Get campaignStateCount resulting in 404"); - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - log.info("Get campaignStateCount resulting in 200"); - return new ResponseEntity<>(stateCountCampaignDto, HttpStatus.OK); + StateCountCampaignDto stateCountCampaignDto; + try { + stateCountCampaignDto = stateService.getStateCountByCampaign(userId, id, date); + } catch (NotFoundException e) { + log.error(e.getMessage()); + log.info("Get campaignStateCount resulting in 404"); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } + log.info("Get campaignStateCount resulting in 200"); + return new ResponseEntity<>(stateCountCampaignDto, HttpStatus.OK); } /** @@ -143,17 +130,13 @@ public ResponseEntity getCampaignStateCount( public ResponseEntity> getInterviewersStateCount( @RequestParam(required = false, name = "date") Long date) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - List stateCountCampaignsDto = stateService.getStateCountByInterviewer(userId, date); - if (stateCountCampaignsDto == null) { - log.info("Get interviewersStateCount resulting in 404"); - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - log.info("Get interviewersStateCount resulting in 200"); - return new ResponseEntity<>(stateCountCampaignsDto, HttpStatus.OK); + List stateCountCampaignsDto = stateService.getStateCountByInterviewer(userId, date); + if (stateCountCampaignsDto == null) { + log.info("Get interviewersStateCount resulting in 404"); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } + log.info("Get interviewersStateCount resulting in 200"); + return new ResponseEntity<>(stateCountCampaignsDto, HttpStatus.OK); } /** @@ -169,16 +152,12 @@ public ResponseEntity> getInterviewersStateCount( public ResponseEntity> getCampaignsStateCount( @RequestParam(required = false, name = "date") Long date) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - List stateCountCampaignsDto = stateService.getStateCountByCampaigns(userId, date); - if (stateCountCampaignsDto == null) { - log.info("Get campaignStateCount resulting in 404"); - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - log.info("Get campaignStateCount resulting in 200"); - return new ResponseEntity<>(stateCountCampaignsDto, HttpStatus.OK); + List stateCountCampaignsDto = stateService.getStateCountByCampaigns(userId, date); + if (stateCountCampaignsDto == null) { + log.info("Get campaignStateCount resulting in 404"); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } + log.info("Get campaignStateCount resulting in 200"); + return new ResponseEntity<>(stateCountCampaignsDto, HttpStatus.OK); } } diff --git a/src/main/java/fr/insee/pearljam/api/controller/SurveyUnitController.java b/src/main/java/fr/insee/pearljam/api/controller/SurveyUnitController.java index 2711fcca..76bad7e2 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/SurveyUnitController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/SurveyUnitController.java @@ -105,9 +105,6 @@ public ResponseEntity postSurveyUnitInterviewerLinks(@RequestBody List> getListSurveyUnit( @RequestParam(value = "extended", defaultValue = "false", required = false) Boolean extended) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } List lstSurveyUnit = surveyUnitService.getSurveyUnitDto(userId, extended); if (lstSurveyUnit == null) { log.info("{} GET SurveyUnits resulting in 404", userId); @@ -128,9 +125,6 @@ public ResponseEntity> getListSurveyUnit( @GetMapping(path = "/survey-unit/{id}") public ResponseEntity getSurveyUnitById(@PathVariable(value = "id") String id) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } Optional su = surveyUnitService.findById(id); if (!su.isPresent()) { log.error("{} : Survey unit with id {} was not found in database", userId, id); @@ -173,9 +167,6 @@ public ResponseEntity updateSurveyUnit( @RequestBody SurveyUnitDetailDto surveyUnitUpdated, @PathVariable(value = "id") String id) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } ResponseEntity updatedSurveyUnitResponse = surveyUnitService.updateSurveyUnitDetail(userId, id, surveyUnitUpdated); HttpStatusCode returnCode = updatedSurveyUnitResponse.getStatusCode(); @@ -222,10 +213,6 @@ public ResponseEntity getSurveyUnitsInTempZone() { public ResponseEntity updateSurveyUnitState( @PathVariable(value = "id") String surveyUnitId, @PathVariable(value = "state") StateType state) { - String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } HttpStatus returnCode = surveyUnitService.addStateToSurveyUnit(surveyUnitId, state); log.info("PUT state '{}' on survey unit {} resulting in {}", state.getLabel(), surveyUnitId, returnCode.value()); @@ -247,9 +234,6 @@ public ResponseEntity closeSurveyUnit( @PathVariable(value = "id") String surveyUnitId, @PathVariable(value = "closingCause") ClosingCauseType closingCause) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } log.info("{} : PUT close with cause '{}' on su {}", userId, closingCause, surveyUnitId); HttpStatus returnCode = surveyUnitService.closeSurveyUnit(surveyUnitId, closingCause); log.info("PUT close with cause '{}' on su {} resulting in {}", closingCause, surveyUnitId, @@ -271,10 +255,6 @@ public ResponseEntity closeSurveyUnit( public ResponseEntity updateClosingCause( @PathVariable(value = "id") String surveyUnitId, @PathVariable(value = "closingCause") ClosingCauseType closingCause) { - String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } HttpStatus returnCode = surveyUnitService.updateClosingCause(surveyUnitId, closingCause); log.info("PUT close with cause '{}' on su {} resulting in {}", closingCause, surveyUnitId, returnCode.value()); @@ -295,9 +275,6 @@ public ResponseEntity updateSurveyUnitComment( @RequestBody CommentDto comment, @PathVariable(value = "id") String surveyUnitId) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } HttpStatus returnCode = surveyUnitService.updateSurveyUnitComment(userId, surveyUnitId, comment); log.info("PUT comment on su {} resulting in {}", surveyUnitId, returnCode.value()); return new ResponseEntity<>(returnCode); @@ -307,9 +284,6 @@ public ResponseEntity updateSurveyUnitComment( @PutMapping(path = "/survey-unit/{id}/viewed") public ResponseEntity updateSurveyUnitViewed(@PathVariable(value = "id") String surveyUnitId) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } HttpStatus returnCode = surveyUnitService.updateSurveyUnitViewed(userId, surveyUnitId); log.info("PUT viewed on su {} resulting in {}", surveyUnitId, returnCode.value()); return new ResponseEntity<>(returnCode); @@ -330,9 +304,6 @@ public ResponseEntity> getSurveyUnitByCampaignId( @PathVariable(value = "id") String id, @RequestParam(value = "state", required = false) String state) { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } Set surveyUnit = surveyUnitService.getSurveyUnitByCampaign(id, userId, state); if (surveyUnit == null) { log.info("{} : GET SurveyUnit with id {} resulting in 404", userId, id); @@ -398,11 +369,6 @@ public ResponseEntity checkHabilitation( public ResponseEntity getStatesBySurveyUnitId( @PathVariable(value = "id") String id) { - String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - log.info("GET states of surveyUnit {} resulting in 403", id); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } log.info("GET states of surveyUnit {} resulting in 403", id); List lstState = surveyUnitService.getListStatesBySurveyUnitId(id); if (lstState.isEmpty()) { @@ -426,11 +392,6 @@ public ResponseEntity> getClosableSurveyUnits(HttpSe String userId = authenticatedUserService.getCurrentUserId(); log.info("{} try to GET closable units", userId); - - if (StringUtils.isBlank(userId)) { - log.info("GET closable survey units resulting in 401"); - return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); - } List lstSu = surveyUnitService.getClosableSurveyUnits(request, userId); log.info("GET closable survey units resulting in 200"); return new ResponseEntity<>(lstSu, HttpStatus.OK); @@ -468,10 +429,6 @@ public ResponseEntity deleteSurveyUnit(@PathVariable(value = "id") Strin @GetMapping(path = "/admin/survey-units") public ResponseEntity> getAllSurveyUnitsId() { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - log.info("GET admin survey units resulting in 401"); - return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); - } List suIds = surveyUnitService.getAllIds(); log.info("{} : GET admin survey units resulting in 200", userId); return new ResponseEntity<>(suIds, HttpStatus.OK); @@ -487,11 +444,6 @@ public ResponseEntity> getAllSurveyUnitsId() { @Operation(summary = "Get survey units id by campaign") @GetMapping(path = "/admin/campaign/{id}/survey-units") public ResponseEntity> getAllSurveyUnitsIdByCampaignId(@PathVariable(value = "id") String id) { - String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - log.info("GET admin survey units for campaign {} resulting in 401", id); - return new ResponseEntity<>(HttpStatus.UNAUTHORIZED); - } List suIds = surveyUnitService.getAllIdsByCampaignId(id); log.info("GET admin survey units for campaign {} resulting in 200", id); return new ResponseEntity<>(suIds, HttpStatus.OK); diff --git a/src/main/java/fr/insee/pearljam/api/controller/UserController.java b/src/main/java/fr/insee/pearljam/api/controller/UserController.java index a43b66e7..118666d3 100644 --- a/src/main/java/fr/insee/pearljam/api/controller/UserController.java +++ b/src/main/java/fr/insee/pearljam/api/controller/UserController.java @@ -52,19 +52,13 @@ public class UserController { @GetMapping(path = "/user") public ResponseEntity getUser() { String userId = authenticatedUserService.getCurrentUserId(); - if (StringUtils.isBlank(userId)) { - log.info("GET User resulting in 403"); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - Optional user = userService.getUser(userId); - if (user.isEmpty()) { - log.info("GET User resulting in 404"); - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - log.info("GET User resulting in 200"); - return new ResponseEntity<>(user.get(), HttpStatus.OK); + Optional user = userService.getUser(userId); + if (user.isEmpty()) { + log.info("GET User resulting in 404"); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } - + log.info("GET User resulting in 200"); + return new ResponseEntity<>(user.get(), HttpStatus.OK); } /** @@ -80,18 +74,13 @@ public ResponseEntity getUserById( @PathVariable(value = "id") String id) { String userId = authenticatedUserService.getCurrentUserId(); log.info("{} try to GET user with id : {}", userId, id); - if (StringUtils.isBlank(userId)) { - log.info("GET User {} resulting in 403", id); - return new ResponseEntity<>(HttpStatus.FORBIDDEN); - } else { - Optional user = userService.getUser(id); - if (user.isEmpty()) { - log.info("GET User resulting in 404"); - return new ResponseEntity<>(HttpStatus.NOT_FOUND); - } - log.info("GET User resulting in 200"); - return new ResponseEntity<>(user.get(), HttpStatus.OK); + Optional user = userService.getUser(id); + if (user.isEmpty()) { + log.info("GET User resulting in 404"); + return new ResponseEntity<>(HttpStatus.NOT_FOUND); } + log.info("GET User resulting in 200"); + return new ResponseEntity<>(user.get(), HttpStatus.OK); } /** From 9c8cb2850d7c51833a572ffeace315ac0dfd16c3 Mon Sep 17 00:00:00 2001 From: davdarras Date: Thu, 20 Jun 2024 13:18:22 +0200 Subject: [PATCH 3/3] refactor: edit changes from review --- .../pearljam/api/configuration/log/PropertiesLogger.java | 9 +-------- .../adapter/AuthenticatedCurrentUserHelperAdapter.java | 4 ++-- .../java/fr/insee/pearljam/api/noAuth/TestNoAuth.java | 2 -- 3 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/main/java/fr/insee/pearljam/api/configuration/log/PropertiesLogger.java b/src/main/java/fr/insee/pearljam/api/configuration/log/PropertiesLogger.java index 569b5b14..2184e492 100644 --- a/src/main/java/fr/insee/pearljam/api/configuration/log/PropertiesLogger.java +++ b/src/main/java/fr/insee/pearljam/api/configuration/log/PropertiesLogger.java @@ -33,14 +33,7 @@ public void onApplicationEvent(@NonNull ApplicationEnvironmentPreparedEvent even .distinct() .filter(Objects::nonNull) .sorted() - .filter(ps -> { - for(String propertyObject : propertyObjects) { - if(ps.startsWith(propertyObject)) { - return true; - } - } - return false; - }) + .filter(ps -> propertyObjects.stream().anyMatch(ps::startsWith)) .forEach(key -> log.info("{} = {}", key, hideProperties(key, environment))); log.info("==============================================================================================="); diff --git a/src/main/java/fr/insee/pearljam/infrastructure/security/adapter/AuthenticatedCurrentUserHelperAdapter.java b/src/main/java/fr/insee/pearljam/infrastructure/security/adapter/AuthenticatedCurrentUserHelperAdapter.java index 038fff8b..bffde3cf 100644 --- a/src/main/java/fr/insee/pearljam/infrastructure/security/adapter/AuthenticatedCurrentUserHelperAdapter.java +++ b/src/main/java/fr/insee/pearljam/infrastructure/security/adapter/AuthenticatedCurrentUserHelperAdapter.java @@ -8,7 +8,7 @@ import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.stereotype.Component; -import java.util.Arrays; +import java.util.stream.Stream; @Component @RequiredArgsConstructor @@ -28,7 +28,7 @@ public boolean hasRole(AuthorityRole role) { @Override public boolean hasAnyRole(AuthorityRole... roles) { - return Arrays.stream(roles) + return Stream.of(roles) .anyMatch(this::hasRole); } diff --git a/src/test/java/fr/insee/pearljam/api/noAuth/TestNoAuth.java b/src/test/java/fr/insee/pearljam/api/noAuth/TestNoAuth.java index aa15d405..357e7c7e 100644 --- a/src/test/java/fr/insee/pearljam/api/noAuth/TestNoAuth.java +++ b/src/test/java/fr/insee/pearljam/api/noAuth/TestNoAuth.java @@ -2,7 +2,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; -import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @@ -147,7 +146,6 @@ void testGetCampaign() throws Exception { void testPutClosingCauseNoPreviousClosingCause() throws Exception { mockMvc.perform(put("/api/survey-unit/11/closing-cause/NPI") .accept(MediaType.APPLICATION_JSON)) - .andDo(print()) .andExpect(status().isOk()); List closingCauses = closingCauseRepository.findBySurveyUnitId("11");