This is an automated email from the ASF dual-hosted git repository.
adamsaghy pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/fineract.git
The following commit(s) were added to refs/heads/develop by this push:
new 5f59091b70 FINERACT-2283: Self-service APIs are disabled by default
5f59091b70 is described below
commit 5f59091b7057cfe08262122fe56f57cb66b10ec6
Author: Adam Saghy <[email protected]>
AuthorDate: Fri May 16 20:44:49 2025 +0200
FINERACT-2283: Self-service APIs are disabled by default
---
.../core/config/FineractProperties.java | 7 ++++
.../sms/serialization/SmsCampaignValidator.java | 4 +-
.../core/config/OAuth2SecurityConfig.java | 23 +++++++++---
.../infrastructure/core/config/SecurityConfig.java | 24 +++++++++---
.../gcm/service/NotificationSenderService.java | 4 +-
.../vote/SelfServiceUserAuthorizationManager.java | 2 +-
.../api/SelfAccountTransferApiResource.java | 3 ++
.../api/SelfBeneficiariesTPTApiResource.java | 3 ++
.../self/client/api/SelfClientsApiResource.java | 3 ++
.../SelfServiceModuleIsEnabledCondition.java} | 14 +++----
.../portfolio/self/config/SelfServiceWarning.java | 43 ++++++++++++++++++++++
.../api/DeviceRegistrationApiConstants.java | 2 +-
.../device}/api/DeviceRegistrationApiResource.java | 13 ++++---
.../self/device}/domain/DeviceRegistration.java | 2 +-
.../device}/domain/DeviceRegistrationData.java | 2 +-
.../domain/DeviceRegistrationRepository.java | 2 +-
.../DeviceRegistrationRepositoryWrapper.java | 4 +-
.../DeviceRegistrationNotFoundException.java | 2 +-
.../DeviceRegistrationReadPlatformService.java | 4 +-
.../DeviceRegistrationReadPlatformServiceImpl.java | 6 +--
.../DeviceRegistrationWritePlatformService.java | 4 +-
...DeviceRegistrationWritePlatformServiceImpl.java | 6 +--
.../self/loanaccount/api/SelfLoansApiResource.java | 3 ++
.../self/pockets/api/PocketApiResource.java | 3 ++
.../products/api/SelfLoanProductsApiResource.java | 3 ++
.../api/SelfSavingsProductsApiResource.java | 3 ++
.../products/api/SelfShareProductsApiResource.java | 3 ++
.../api/SelfServiceRegistrationApiResource.java | 3 ++
.../self/runreport/SelfRunReportApiResource.java | 3 ++
.../self/savings/api/SelfSavingsApiResource.java | 3 ++
.../api/SelfAuthenticationApiResource.java | 3 ++
.../self/security/api/SelfUserApiResource.java | 3 ++
.../security/api/SelfUserDetailsApiResource.java | 3 ++
.../api/SelfShareAccountsApiResource.java | 3 ++
.../self/spm/api/SelfScorecardApiResource.java | 3 ++
.../portfolio/self/spm/api/SelfSpmApiResource.java | 3 ++
.../src/main/resources/application.properties | 2 +
.../src/test/resources/application-test.properties | 1 +
.../SavingsAccountsExternalIdTest.java | 2 +-
39 files changed, 178 insertions(+), 46 deletions(-)
diff --git
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
index ed4064aa0a..d6aa63b324 100644
---
a/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
+++
b/fineract-core/src/main/java/org/apache/fineract/infrastructure/core/config/FineractProperties.java
@@ -548,6 +548,7 @@ public class FineractProperties {
public static class FineractModulesProperties {
private FineractInvestorModuleProperties investor;
+ private FineractSelfServiceModuleProperties selfService;
}
@Getter
@@ -556,6 +557,12 @@ public class FineractProperties {
}
+ @Getter
+ @Setter
+ public static class FineractSelfServiceModuleProperties extends
AbstractFineractModuleProperties {
+
+ }
+
@Getter
@Setter
public static class FineractSqlValidationProperties {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/serialization/SmsCampaignValidator.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/serialization/SmsCampaignValidator.java
index 0861a68fee..8dd9c077aa 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/serialization/SmsCampaignValidator.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/campaigns/sms/serialization/SmsCampaignValidator.java
@@ -36,10 +36,10 @@ import
org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
import
org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
-import org.apache.fineract.infrastructure.gcm.domain.DeviceRegistration;
-import
org.apache.fineract.infrastructure.gcm.domain.DeviceRegistrationRepositoryWrapper;
import org.apache.fineract.portfolio.calendar.domain.CalendarFrequencyType;
import org.apache.fineract.portfolio.client.domain.Client;
+import org.apache.fineract.portfolio.self.device.domain.DeviceRegistration;
+import
org.apache.fineract.portfolio.self.device.domain.DeviceRegistrationRepositoryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/OAuth2SecurityConfig.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/OAuth2SecurityConfig.java
index e20ba55560..0b7346c28a 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/OAuth2SecurityConfig.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/OAuth2SecurityConfig.java
@@ -25,7 +25,9 @@ import static
org.springframework.security.authorization.AuthorityAuthorizationM
import static
org.springframework.security.authorization.AuthorizationManagers.allOf;
import static
org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
+import java.util.ArrayList;
import java.util.Collection;
+import java.util.List;
import
org.apache.fineract.infrastructure.businessdate.service.BusinessDateReadPlatformService;
import
org.apache.fineract.infrastructure.cache.service.CacheWritePlatformService;
import
org.apache.fineract.infrastructure.configuration.domain.ConfigurationDomainService;
@@ -47,8 +49,10 @@ import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.Converter;
import org.springframework.http.HttpMethod;
+import org.springframework.security.authorization.AuthorizationManager;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
@@ -61,6 +65,7 @@ import
org.springframework.security.oauth2.core.OAuth2ErrorCodes;
import org.springframework.security.oauth2.jwt.Jwt;
import
org.springframework.security.oauth2.server.resource.authentication.JwtGrantedAuthoritiesConverter;
import org.springframework.security.web.SecurityFilterChain;
+import
org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import
org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.security.web.context.SecurityContextHolderFilter;
@@ -101,17 +106,25 @@ public class OAuth2SecurityConfig {
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception
{
http //
.securityMatcher(antMatcher("/api/**")).authorizeHttpRequests((auth) -> {
+ List<AuthorizationManager<RequestAuthorizationContext>>
authorizationManagers = new ArrayList<>();
+ authorizationManagers.add(fullyAuthenticated());
+
authorizationManagers.add(hasAuthority("TWOFACTOR_AUTHENTICATED"));
+ if
(fineractProperties.getModule().getSelfService().isEnabled()) {
+ auth.requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/self/authentication")).permitAll() //
+ .requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/self/registration")).permitAll() //
+ .requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/self/registration/user")).permitAll(); //
+
authorizationManagers.add(selfServiceUserAuthManager());
+ }
+
auth.requestMatchers(antMatcher(HttpMethod.OPTIONS,
"/api/**")).permitAll() //
.requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/echo")).permitAll() //
.requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/authentication")).permitAll() //
- .requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/self/authentication")).permitAll() //
- .requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/self/registration")).permitAll() //
- .requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/self/registration/user")).permitAll() //
.requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/twofactor/validate")).fullyAuthenticated() //
.requestMatchers(antMatcher("/api/*/twofactor")).fullyAuthenticated() //
.requestMatchers(antMatcher("/api/**"))
- .access(allOf(fullyAuthenticated(),
hasAuthority("TWOFACTOR_AUTHENTICATED"), selfServiceUserAuthManager())); //
- }).csrf((csrf) -> csrf.disable()) // NOSONAR only creating a
service that is used by non-browser clients
+ .access(allOf(authorizationManagers.toArray(new
AuthorizationManager[0]))); //
+ }).csrf(AbstractHttpConfigurer::disable) // NOSONAR only
creating a service that is used by non-browser
+ // clients
.exceptionHandling((ehc) -> ehc.authenticationEntryPoint(new
OAuth2ExceptionEntryPoint()))
.oauth2ResourceServer(oauth2 -> oauth2.jwt(jwt ->
jwt.jwtAuthenticationConverter(authenticationConverter()))
.authenticationEntryPoint(new
OAuth2ExceptionEntryPoint())) //
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java
index 2aa96f7e5f..92e0a068f8 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/core/config/SecurityConfig.java
@@ -19,11 +19,13 @@
package org.apache.fineract.infrastructure.core.config;
+import static
org.apache.fineract.infrastructure.security.vote.SelfServiceUserAuthorizationManager.selfServiceUserAuthManager;
import static
org.springframework.security.authorization.AuthenticatedAuthorizationManager.fullyAuthenticated;
import static
org.springframework.security.authorization.AuthorityAuthorizationManager.hasAuthority;
import static
org.springframework.security.authorization.AuthorizationManagers.allOf;
import static
org.springframework.security.web.util.matcher.AntPathRequestMatcher.antMatcher;
+import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import org.apache.fineract.commands.domain.CommandSourceRepository;
@@ -60,14 +62,17 @@ import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import
org.springframework.security.authentication.dao.DaoAuthenticationProvider;
+import org.springframework.security.authorization.AuthorizationManager;
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.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.ExceptionTranslationFilter;
+import
org.springframework.security.web.access.intercept.RequestAuthorizationContext;
import
org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint;
import org.springframework.security.web.context.SecurityContextHolderFilter;
import org.springframework.web.cors.CorsConfiguration;
@@ -123,20 +128,27 @@ public class SecurityConfig {
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception
{
http //
.securityMatcher(antMatcher("/api/**")).authorizeHttpRequests((auth) -> {
+ List<AuthorizationManager<RequestAuthorizationContext>>
authorizationManagers = new ArrayList<>();
+ authorizationManagers.add(fullyAuthenticated());
+
authorizationManagers.add(hasAuthority("TWOFACTOR_AUTHENTICATED"));
+ if
(fineractProperties.getModule().getSelfService().isEnabled()) {
+ auth.requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/self/authentication")).permitAll() //
+ .requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/self/registration")).permitAll() //
+ .requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/self/registration/user")).permitAll(); //
+
authorizationManagers.add(selfServiceUserAuthManager());
+ }
auth.requestMatchers(antMatcher(HttpMethod.OPTIONS,
"/api/**")).permitAll() //
.requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/echo")).permitAll() //
.requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/authentication")).permitAll() //
- .requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/self/authentication")).permitAll() //
- .requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/self/registration")).permitAll() //
- .requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/self/registration/user")).permitAll() //
.requestMatchers(antMatcher(HttpMethod.PUT,
"/api/*/instance-mode")).permitAll() //
.requestMatchers(antMatcher(HttpMethod.POST,
"/api/*/twofactor/validate")).fullyAuthenticated() //
.requestMatchers(antMatcher("/api/*/twofactor")).fullyAuthenticated() //
.requestMatchers(antMatcher("/api/**"))
- .access(allOf(fullyAuthenticated(),
hasAuthority("TWOFACTOR_AUTHENTICATED"))); //
+ .access(allOf(authorizationManagers.toArray(new
AuthorizationManager[0]))); //
}).httpBasic((httpBasic) ->
httpBasic.authenticationEntryPoint(basicAuthenticationEntryPoint())) //
- .cors(Customizer.withDefaults()).csrf((csrf) ->
csrf.disable()) // NOSONAR only creating a service that
-
// is used by non-browser clients
+
.cors(Customizer.withDefaults()).csrf(AbstractHttpConfigurer::disable) //
NOSONAR only creating a
+
// service that
+ // is used by non-browser clients
.sessionManagement((smc) ->
smc.sessionCreationPolicy(SessionCreationPolicy.STATELESS)) //
.addFilterBefore(tenantAwareBasicAuthenticationFilter(),
SecurityContextHolderFilter.class) //
.addFilterAfter(requestResponseFilter(),
ExceptionTranslationFilter.class) //
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/NotificationSenderService.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/NotificationSenderService.java
index 53eb36764f..39a8a340c0 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/NotificationSenderService.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/NotificationSenderService.java
@@ -27,8 +27,6 @@ import lombok.RequiredArgsConstructor;
import
org.apache.fineract.infrastructure.configuration.service.ExternalServicesPropertiesReadPlatformService;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.infrastructure.gcm.GcmConstants;
-import org.apache.fineract.infrastructure.gcm.domain.DeviceRegistration;
-import
org.apache.fineract.infrastructure.gcm.domain.DeviceRegistrationRepositoryWrapper;
import org.apache.fineract.infrastructure.gcm.domain.Message;
import org.apache.fineract.infrastructure.gcm.domain.Message.Priority;
import org.apache.fineract.infrastructure.gcm.domain.Notification;
@@ -38,6 +36,8 @@ import org.apache.fineract.infrastructure.gcm.domain.Sender;
import org.apache.fineract.infrastructure.sms.domain.SmsMessage;
import org.apache.fineract.infrastructure.sms.domain.SmsMessageRepository;
import org.apache.fineract.infrastructure.sms.domain.SmsMessageStatusType;
+import org.apache.fineract.portfolio.self.device.domain.DeviceRegistration;
+import
org.apache.fineract.portfolio.self.device.domain.DeviceRegistrationRepositoryWrapper;
import org.springframework.stereotype.Service;
@Service
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/vote/SelfServiceUserAuthorizationManager.java
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/vote/SelfServiceUserAuthorizationManager.java
index 0bb9197267..1b40ed45d1 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/vote/SelfServiceUserAuthorizationManager.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/infrastructure/security/vote/SelfServiceUserAuthorizationManager.java
@@ -33,7 +33,7 @@ public class SelfServiceUserAuthorizationManager implements
AuthorizationManager
AppUser user = (AppUser) authentication.get().getPrincipal();
String pathURL = fi.getRequest().getRequestURL().toString();
- boolean isSelfServiceRequest = (pathURL != null &&
pathURL.contains("/self/"));
+ boolean isSelfServiceRequest = pathURL.contains("/self/");
boolean notAllowed = ((isSelfServiceRequest &&
!user.isSelfServiceUser())
|| (!isSelfServiceRequest && user.isSelfServiceUser()));
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfAccountTransferApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfAccountTransferApiResource.java
index 963f87b6da..c2712a1ab1 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfAccountTransferApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfAccountTransferApiResource.java
@@ -57,13 +57,16 @@ import
org.apache.fineract.portfolio.self.account.exception.BeneficiaryTransferL
import
org.apache.fineract.portfolio.self.account.exception.DailyTPTTransactionAmountLimitExceededException;
import
org.apache.fineract.portfolio.self.account.service.SelfAccountTransferReadService;
import
org.apache.fineract.portfolio.self.account.service.SelfBeneficiariesTPTReadPlatformService;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/accounttransfers")
@Component
@Tag(name = "Self Account transfer", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfAccountTransferApiResource {
private final PlatformSecurityContext context;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfBeneficiariesTPTApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfBeneficiariesTPTApiResource.java
index 8833e34aba..ba2067ebdd 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfBeneficiariesTPTApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/account/api/SelfBeneficiariesTPTApiResource.java
@@ -56,12 +56,15 @@ import
org.apache.fineract.portfolio.account.PortfolioAccountType;
import
org.apache.fineract.portfolio.account.service.AccountTransferEnumerations;
import
org.apache.fineract.portfolio.self.account.data.SelfBeneficiariesTPTData;
import
org.apache.fineract.portfolio.self.account.service.SelfBeneficiariesTPTReadPlatformService;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/beneficiaries/tpt")
@Component
@Tag(name = "Self Third Party Transfer", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfBeneficiariesTPTApiResource {
private final PlatformSecurityContext context;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/api/SelfClientsApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/api/SelfClientsApiResource.java
index f149a8c84e..4897cd22c4 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/api/SelfClientsApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/client/api/SelfClientsApiResource.java
@@ -53,16 +53,19 @@ import
org.apache.fineract.portfolio.client.api.ClientsApiResource;
import org.apache.fineract.portfolio.client.exception.ClientNotFoundException;
import org.apache.fineract.portfolio.self.client.data.SelfClientDataValidator;
import
org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
import org.apache.fineract.useradministration.domain.AppUser;
import org.glassfish.jersey.media.multipart.FormDataBodyPart;
import org.glassfish.jersey.media.multipart.FormDataContentDisposition;
import org.glassfish.jersey.media.multipart.FormDataParam;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/clients")
@Component
@Tag(name = "Self Client", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfClientsApiResource {
private final PlatformSecurityContext context;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/api/DeviceRegistrationApiConstants.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/config/SelfServiceModuleIsEnabledCondition.java
similarity index 65%
copy from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/api/DeviceRegistrationApiConstants.java
copy to
fineract-provider/src/main/java/org/apache/fineract/portfolio/self/config/SelfServiceModuleIsEnabledCondition.java
index a0cf67cbd0..fa4fe3e010 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/api/DeviceRegistrationApiConstants.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/config/SelfServiceModuleIsEnabledCondition.java
@@ -16,15 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.gcm.api;
+package org.apache.fineract.portfolio.self.config;
-public final class DeviceRegistrationApiConstants {
+import org.apache.fineract.infrastructure.core.condition.PropertiesCondition;
+import org.apache.fineract.infrastructure.core.config.FineractProperties;
- private DeviceRegistrationApiConstants() {
+public class SelfServiceModuleIsEnabledCondition extends PropertiesCondition {
+ @Override
+ protected boolean matches(FineractProperties properties) {
+ return properties.getModule().getSelfService().isEnabled();
}
-
- public static final String clientIdParamName = "clientId";
- public static final String registrationIdParamName = "registrationId";
-
}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/config/SelfServiceWarning.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/config/SelfServiceWarning.java
new file mode 100644
index 0000000000..c9fd5d7fdf
--- /dev/null
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/config/SelfServiceWarning.java
@@ -0,0 +1,43 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.fineract.portfolio.self.config;
+
+import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.context.annotation.Conditional;
+import org.springframework.stereotype.Component;
+
+@Component
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
+@Slf4j
+public class SelfServiceWarning implements InitializingBean {
+
+ @Override
+ @SuppressFBWarnings("SLF4J_SIGN_ONLY_FORMAT")
+ public void afterPropertiesSet() throws Exception {
+
log.warn("------------------------------------------------------------");
+ log.warn("
");
+ log.warn("DO NOT USE THIS IN PRODUCTION!");
+ log.warn("Self service capabilities of Fineract are NOT considered
safe!");
+ log.warn("DO NOT USE THIS IN PRODUCTION!");
+ log.warn("
");
+
log.warn("------------------------------------------------------------");
+ }
+}
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/api/DeviceRegistrationApiConstants.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/api/DeviceRegistrationApiConstants.java
similarity index 95%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/api/DeviceRegistrationApiConstants.java
rename to
fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/api/DeviceRegistrationApiConstants.java
index a0cf67cbd0..42ca444d19 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/api/DeviceRegistrationApiConstants.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/api/DeviceRegistrationApiConstants.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.gcm.api;
+package org.apache.fineract.portfolio.self.device.api;
public final class DeviceRegistrationApiConstants {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/api/DeviceRegistrationApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/api/DeviceRegistrationApiResource.java
similarity index 90%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/api/DeviceRegistrationApiResource.java
rename to
fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/api/DeviceRegistrationApiResource.java
index 91b8aff3a5..cb61251607 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/api/DeviceRegistrationApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/api/DeviceRegistrationApiResource.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.gcm.api;
+package org.apache.fineract.portfolio.self.device.api;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
@@ -36,17 +36,20 @@ import java.util.Collection;
import java.util.HashMap;
import lombok.RequiredArgsConstructor;
import
org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
-import org.apache.fineract.infrastructure.gcm.domain.DeviceRegistration;
-import org.apache.fineract.infrastructure.gcm.domain.DeviceRegistrationData;
-import
org.apache.fineract.infrastructure.gcm.service.DeviceRegistrationReadPlatformService;
-import
org.apache.fineract.infrastructure.gcm.service.DeviceRegistrationWritePlatformService;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
+import org.apache.fineract.portfolio.self.device.domain.DeviceRegistration;
+import org.apache.fineract.portfolio.self.device.domain.DeviceRegistrationData;
+import
org.apache.fineract.portfolio.self.device.service.DeviceRegistrationReadPlatformService;
+import
org.apache.fineract.portfolio.self.device.service.DeviceRegistrationWritePlatformService;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/device/registration")
@Component
@Tag(name = "Device Registration", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class DeviceRegistrationApiResource {
private final PlatformSecurityContext context;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/domain/DeviceRegistration.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/domain/DeviceRegistration.java
similarity index 97%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/domain/DeviceRegistration.java
rename to
fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/domain/DeviceRegistration.java
index 6e13887b43..c94b0c22a3 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/domain/DeviceRegistration.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/domain/DeviceRegistration.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.gcm.domain;
+package org.apache.fineract.portfolio.self.device.domain;
import jakarta.persistence.Column;
import jakarta.persistence.Entity;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/domain/DeviceRegistrationData.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/domain/DeviceRegistrationData.java
similarity index 96%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/domain/DeviceRegistrationData.java
rename to
fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/domain/DeviceRegistrationData.java
index 44247d4090..c5dc7c7040 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/domain/DeviceRegistrationData.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/domain/DeviceRegistrationData.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.gcm.domain;
+package org.apache.fineract.portfolio.self.device.domain;
import java.time.OffsetDateTime;
import lombok.Getter;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/domain/DeviceRegistrationRepository.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/domain/DeviceRegistrationRepository.java
similarity index 96%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/domain/DeviceRegistrationRepository.java
rename to
fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/domain/DeviceRegistrationRepository.java
index 53f22fd7ef..68a0d25a5a 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/domain/DeviceRegistrationRepository.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/domain/DeviceRegistrationRepository.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.gcm.domain;
+package org.apache.fineract.portfolio.self.device.domain;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/domain/DeviceRegistrationRepositoryWrapper.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/domain/DeviceRegistrationRepositoryWrapper.java
similarity index 92%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/domain/DeviceRegistrationRepositoryWrapper.java
rename to
fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/domain/DeviceRegistrationRepositoryWrapper.java
index c99c5b5233..e971ea5457 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/domain/DeviceRegistrationRepositoryWrapper.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/domain/DeviceRegistrationRepositoryWrapper.java
@@ -16,9 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.gcm.domain;
+package org.apache.fineract.portfolio.self.device.domain;
-import
org.apache.fineract.infrastructure.gcm.exception.DeviceRegistrationNotFoundException;
+import
org.apache.fineract.portfolio.self.device.exception.DeviceRegistrationNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/exception/DeviceRegistrationNotFoundException.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/exception/DeviceRegistrationNotFoundException.java
similarity index 97%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/exception/DeviceRegistrationNotFoundException.java
rename to
fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/exception/DeviceRegistrationNotFoundException.java
index a5f8aa0e22..3a0d92a491 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/exception/DeviceRegistrationNotFoundException.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/exception/DeviceRegistrationNotFoundException.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.gcm.exception;
+package org.apache.fineract.portfolio.self.device.exception;
import
org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
import org.springframework.dao.EmptyResultDataAccessException;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationReadPlatformService.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/service/DeviceRegistrationReadPlatformService.java
similarity index 88%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationReadPlatformService.java
rename to
fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/service/DeviceRegistrationReadPlatformService.java
index dd1e0490fd..3834b4e54b 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationReadPlatformService.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/service/DeviceRegistrationReadPlatformService.java
@@ -16,10 +16,10 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.gcm.service;
+package org.apache.fineract.portfolio.self.device.service;
import java.util.Collection;
-import org.apache.fineract.infrastructure.gcm.domain.DeviceRegistrationData;
+import org.apache.fineract.portfolio.self.device.domain.DeviceRegistrationData;
public interface DeviceRegistrationReadPlatformService {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationReadPlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/service/DeviceRegistrationReadPlatformServiceImpl.java
similarity index 95%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationReadPlatformServiceImpl.java
rename to
fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/service/DeviceRegistrationReadPlatformServiceImpl.java
index c21e0c844c..203b569bdf 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationReadPlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/service/DeviceRegistrationReadPlatformServiceImpl.java
@@ -16,17 +16,17 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.gcm.service;
+package org.apache.fineract.portfolio.self.device.service;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.OffsetDateTime;
import java.util.Collection;
import org.apache.fineract.infrastructure.core.domain.JdbcSupport;
-import org.apache.fineract.infrastructure.gcm.domain.DeviceRegistrationData;
-import
org.apache.fineract.infrastructure.gcm.exception.DeviceRegistrationNotFoundException;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.client.data.ClientData;
+import org.apache.fineract.portfolio.self.device.domain.DeviceRegistrationData;
+import
org.apache.fineract.portfolio.self.device.exception.DeviceRegistrationNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.EmptyResultDataAccessException;
import org.springframework.jdbc.core.JdbcTemplate;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationWritePlatformService.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/service/DeviceRegistrationWritePlatformService.java
similarity index 88%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationWritePlatformService.java
rename to
fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/service/DeviceRegistrationWritePlatformService.java
index f10975b609..d8b1f2b9b0 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationWritePlatformService.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/service/DeviceRegistrationWritePlatformService.java
@@ -16,9 +16,9 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.gcm.service;
+package org.apache.fineract.portfolio.self.device.service;
-import org.apache.fineract.infrastructure.gcm.domain.DeviceRegistration;
+import org.apache.fineract.portfolio.self.device.domain.DeviceRegistration;
public interface DeviceRegistrationWritePlatformService {
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationWritePlatformServiceImpl.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/service/DeviceRegistrationWritePlatformServiceImpl.java
similarity index 95%
rename from
fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationWritePlatformServiceImpl.java
rename to
fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/service/DeviceRegistrationWritePlatformServiceImpl.java
index 09d54481ef..1b77f78bcd 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/infrastructure/gcm/service/DeviceRegistrationWritePlatformServiceImpl.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/device/service/DeviceRegistrationWritePlatformServiceImpl.java
@@ -16,7 +16,7 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.fineract.infrastructure.gcm.service;
+package org.apache.fineract.portfolio.self.device.service;
import jakarta.persistence.EntityExistsException;
import jakarta.persistence.PersistenceException;
@@ -24,11 +24,11 @@ import org.apache.commons.lang3.exception.ExceptionUtils;
import org.apache.fineract.infrastructure.core.exception.ErrorHandler;
import
org.apache.fineract.infrastructure.core.exception.PlatformDataIntegrityException;
import org.apache.fineract.infrastructure.core.service.DateUtils;
-import org.apache.fineract.infrastructure.gcm.domain.DeviceRegistration;
-import
org.apache.fineract.infrastructure.gcm.domain.DeviceRegistrationRepositoryWrapper;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.client.domain.Client;
import org.apache.fineract.portfolio.client.domain.ClientRepositoryWrapper;
+import org.apache.fineract.portfolio.self.device.domain.DeviceRegistration;
+import
org.apache.fineract.portfolio.self.device.domain.DeviceRegistrationRepositoryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.orm.jpa.JpaSystemException;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/loanaccount/api/SelfLoansApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/loanaccount/api/SelfLoansApiResource.java
index 79b0e5b877..d87e353cb7 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/loanaccount/api/SelfLoansApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/loanaccount/api/SelfLoansApiResource.java
@@ -56,15 +56,18 @@ import
org.apache.fineract.portfolio.loanaccount.exception.NotSupportedLoanTempl
import
org.apache.fineract.portfolio.loanaccount.guarantor.api.GuarantorsApiResource;
import org.apache.fineract.portfolio.loanaccount.guarantor.data.GuarantorData;
import
org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
import
org.apache.fineract.portfolio.self.loanaccount.data.SelfLoansDataValidator;
import
org.apache.fineract.portfolio.self.loanaccount.service.AppuserLoansMapperReadService;
import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/loans")
@Component
@Tag(name = "Self Loans", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfLoansApiResource {
private final PlatformSecurityContext context;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/pockets/api/PocketApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/pockets/api/PocketApiResource.java
index bc33cd3d73..62c9be04fa 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/pockets/api/PocketApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/pockets/api/PocketApiResource.java
@@ -43,13 +43,16 @@ import
org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformS
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import
org.apache.fineract.infrastructure.core.exception.UnrecognizedQueryParamException;
import
org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
import
org.apache.fineract.portfolio.self.pockets.service.PocketAccountMappingReadPlatformService;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/pockets")
@Component
@Tag(name = "Pocket", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class PocketApiResource {
private final PortfolioCommandSourceWritePlatformService
commandsSourceWritePlatformService;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfLoanProductsApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfLoanProductsApiResource.java
index 7569a08605..5149a87c88 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfLoanProductsApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfLoanProductsApiResource.java
@@ -33,6 +33,8 @@ import lombok.RequiredArgsConstructor;
import org.apache.fineract.portfolio.loanaccount.api.LoanApiConstants;
import org.apache.fineract.portfolio.loanproduct.api.LoanProductsApiResource;
import
org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/loanproducts")
@@ -114,6 +116,7 @@ import org.springframework.stereotype.Component;
+ "If Specified as true, arrears will be identified based on original
schedule.\n" + "allowAttributeOverrides\n"
+ "Specifies if select attributes may be overridden for individual
loan accounts.")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfLoanProductsApiResource {
private final LoanProductsApiResource loanProductsApiResource;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfSavingsProductsApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfSavingsProductsApiResource.java
index f83c64e03b..4db3b2f723 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfSavingsProductsApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfSavingsProductsApiResource.java
@@ -33,12 +33,15 @@ import lombok.RequiredArgsConstructor;
import org.apache.fineract.portfolio.savings.SavingsApiConstants;
import org.apache.fineract.portfolio.savings.api.SavingsProductsApiResource;
import
org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/savingsproducts")
@Component
@Tag(name = "Self Savings Products", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfSavingsProductsApiResource {
private final SavingsProductsApiResource savingsProductsApiResource;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfShareProductsApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfShareProductsApiResource.java
index 0b005291e2..b3e8ae73c1 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfShareProductsApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/products/api/SelfShareProductsApiResource.java
@@ -33,12 +33,15 @@ import lombok.RequiredArgsConstructor;
import
org.apache.fineract.portfolio.accounts.constants.ShareAccountApiConstants;
import org.apache.fineract.portfolio.products.api.ProductsApiResource;
import
org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/products/share")
@Component
@Tag(name = "Self Share Products", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfShareProductsApiResource {
private final ProductsApiResource productsApiResource;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/api/SelfServiceRegistrationApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/api/SelfServiceRegistrationApiResource.java
index 4f4d777134..725079967e 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/api/SelfServiceRegistrationApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/registration/api/SelfServiceRegistrationApiResource.java
@@ -27,15 +27,18 @@ import jakarta.ws.rs.core.MediaType;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
import
org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
import org.apache.fineract.portfolio.self.registration.SelfServiceApiConstants;
import
org.apache.fineract.portfolio.self.registration.service.SelfServiceRegistrationWritePlatformService;
import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/registration")
@Component
@Tag(name = "Self Service Registration", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfServiceRegistrationApiResource {
private final SelfServiceRegistrationWritePlatformService
selfServiceRegistrationWritePlatformService;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/runreport/SelfRunReportApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/runreport/SelfRunReportApiResource.java
index 9de8297741..fa4bfdd1e9 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/runreport/SelfRunReportApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/runreport/SelfRunReportApiResource.java
@@ -37,6 +37,8 @@ import jakarta.ws.rs.core.UriInfo;
import lombok.RequiredArgsConstructor;
import
org.apache.fineract.infrastructure.dataqueries.api.RunreportsApiResource;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/runreports")
@@ -51,6 +53,7 @@ import org.springframework.stereotype.Component;
+ "\n" + "ARGUMENTS\n"
+ "R_'parameter names' ... optional, No defaults The number and names
of the parameters depend on the specific report and how it has been configured.
R_officeId is an example parameter name.Note: the prefix R_ stands for
ReportinggenericResultSetoptional, defaults to true If 'true' an optimised JSON
format is returned suitable for tabular display of data. If 'false' a simple
JSON format is returned. parameterType optional, The only valid value is
'true'. If any other value is pro [...]
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfRunReportApiResource {
private final PlatformSecurityContext context;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/savings/api/SelfSavingsApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/savings/api/SelfSavingsApiResource.java
index 0239e385a2..f7c1cb8b03 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/savings/api/SelfSavingsApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/savings/api/SelfSavingsApiResource.java
@@ -52,16 +52,19 @@ import
org.apache.fineract.portfolio.savings.api.SavingsApiSetConstants;
import org.apache.fineract.portfolio.savings.data.SavingsAccountData;
import
org.apache.fineract.portfolio.savings.exception.SavingsAccountNotFoundException;
import
org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
import
org.apache.fineract.portfolio.self.savings.data.SelfSavingsAccountConstants;
import
org.apache.fineract.portfolio.self.savings.data.SelfSavingsDataValidator;
import
org.apache.fineract.portfolio.self.savings.service.AppuserSavingsMapperReadService;
import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/savingsaccounts")
@Component
@Tag(name = "Self Savings Account", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfSavingsApiResource {
private final PlatformSecurityContext context;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfAuthenticationApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfAuthenticationApiResource.java
index 58e35f8060..72be491d6e 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfAuthenticationApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfAuthenticationApiResource.java
@@ -33,7 +33,9 @@ import jakarta.ws.rs.core.MediaType;
import lombok.RequiredArgsConstructor;
import
org.apache.fineract.infrastructure.security.api.AuthenticationApiResource;
import
org.apache.fineract.infrastructure.security.api.AuthenticationApiResourceSwagger;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Component
@@ -41,6 +43,7 @@ import org.springframework.stereotype.Component;
@Path("/v1/self/authentication")
@Tag(name = "Self Authentication", description = "Authenticates the
credentials provided and returns the set roles and permissions allowed")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfAuthenticationApiResource {
private final AuthenticationApiResource authenticationApiResource;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfUserApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfUserApiResource.java
index 69053d53c5..b627aafd72 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfUserApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfUserApiResource.java
@@ -40,14 +40,17 @@ import org.apache.commons.lang3.StringUtils;
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
import org.apache.fineract.useradministration.api.UsersApiResource;
import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/user")
@Component
@Tag(name = "Self User", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfUserApiResource {
private final UsersApiResource usersApiResource;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfUserDetailsApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfUserDetailsApiResource.java
index 7b74b5dc18..ef31febdab 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfUserDetailsApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/security/api/SelfUserDetailsApiResource.java
@@ -30,7 +30,9 @@ import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.security.api.UserDetailsApiResource;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/userdetails")
@@ -38,6 +40,7 @@ import org.springframework.stereotype.Component;
@ConditionalOnProperty("fineract.security.oauth.enabled")
@Tag(name = "Self User Details", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfUserDetailsApiResource {
private final UserDetailsApiResource userDetailsApiResource;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/api/SelfShareAccountsApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/api/SelfShareAccountsApiResource.java
index f1907825f0..2f42ab38ac 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/api/SelfShareAccountsApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/shareaccounts/api/SelfShareAccountsApiResource.java
@@ -57,17 +57,20 @@ import
org.apache.fineract.portfolio.client.exception.ClientNotFoundException;
import org.apache.fineract.portfolio.products.data.ProductData;
import
org.apache.fineract.portfolio.products.service.ShareProductReadPlatformService;
import
org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
import
org.apache.fineract.portfolio.self.shareaccounts.data.SelfShareAccountsDataValidator;
import
org.apache.fineract.portfolio.self.shareaccounts.service.AppUserShareAccountsMapperReadPlatformService;
import org.apache.fineract.portfolio.shareaccounts.data.ShareAccountData;
import
org.apache.fineract.portfolio.shareaccounts.service.ShareAccountReadPlatformService;
import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
@Path("/v1/self/shareaccounts")
@Component
@Tag(name = "Self Share Accounts", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfShareAccountsApiResource {
private final PlatformSecurityContext context;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/spm/api/SelfScorecardApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/spm/api/SelfScorecardApiResource.java
index 16af1027e1..24eac5f78d 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/spm/api/SelfScorecardApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/spm/api/SelfScorecardApiResource.java
@@ -32,9 +32,11 @@ import lombok.RequiredArgsConstructor;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
import org.apache.fineract.portfolio.client.exception.ClientNotFoundException;
import
org.apache.fineract.portfolio.self.client.service.AppuserClientMapperReadService;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
import org.apache.fineract.spm.api.ScorecardApiResource;
import org.apache.fineract.spm.data.ScorecardData;
import org.apache.fineract.useradministration.domain.AppUser;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@@ -42,6 +44,7 @@ import
org.springframework.transaction.annotation.Transactional;
@Component
@Tag(name = "Self Score Card", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfScorecardApiResource {
private final PlatformSecurityContext context;
diff --git
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/spm/api/SelfSpmApiResource.java
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/spm/api/SelfSpmApiResource.java
index d288e8dcf5..483b41da08 100644
---
a/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/spm/api/SelfSpmApiResource.java
+++
b/fineract-provider/src/main/java/org/apache/fineract/portfolio/self/spm/api/SelfSpmApiResource.java
@@ -28,8 +28,10 @@ import jakarta.ws.rs.core.MediaType;
import java.util.List;
import lombok.RequiredArgsConstructor;
import
org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
+import
org.apache.fineract.portfolio.self.config.SelfServiceModuleIsEnabledCondition;
import org.apache.fineract.spm.api.SpmApiResource;
import org.apache.fineract.spm.data.SurveyData;
+import org.springframework.context.annotation.Conditional;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
@@ -37,6 +39,7 @@ import
org.springframework.transaction.annotation.Transactional;
@Component
@Tag(name = "Self Spm", description = "")
@RequiredArgsConstructor
+@Conditional(SelfServiceModuleIsEnabledCondition.class)
public class SelfSpmApiResource {
private final PlatformSecurityContext securityContext;
diff --git a/fineract-provider/src/main/resources/application.properties
b/fineract-provider/src/main/resources/application.properties
index a627c44d21..3dd6a5a662 100644
--- a/fineract-provider/src/main/resources/application.properties
+++ b/fineract-provider/src/main/resources/application.properties
@@ -183,6 +183,8 @@
fineract.sampling.samplingRate=${FINERACT_SAMPLING_RATE:1000}
fineract.sampling.sampledClasses=${FINERACT_SAMPLED_CLASSES:}
fineract.sampling.resetPeriodSec=${FINERACT_SAMPLING_RESET_PERIOD_IN_SEC:60}
+#Modules
+fineract.module.self-service.enabled=${FINERACT_MODULE_SELF_SERVICE_ENABLED:false}
fineract.module.investor.enabled=${FINERACT_MODULE_INVESTOR_ENABLED:true}
fineract.insecure-http-client=${FINERACT_INSECURE_HTTP_CLIENT:true}
diff --git a/fineract-provider/src/test/resources/application-test.properties
b/fineract-provider/src/test/resources/application-test.properties
index a7d6336e62..6d5f46f4db 100644
--- a/fineract-provider/src/test/resources/application-test.properties
+++ b/fineract-provider/src/test/resources/application-test.properties
@@ -105,6 +105,7 @@ fineract.sampling.enabled=false
fineract.sampling.sampledClasses=
fineract.module.investor.enabled=true
+fineract.module.self-service.enabled=true
# sql validation
diff --git
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsAccountsExternalIdTest.java
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsAccountsExternalIdTest.java
index 2f2b13621d..ee1639b1d9 100644
---
a/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsAccountsExternalIdTest.java
+++
b/integration-tests/src/test/java/org/apache/fineract/integrationtests/SavingsAccountsExternalIdTest.java
@@ -144,7 +144,7 @@ public class SavingsAccountsExternalIdTest extends
IntegrationTest {
request.dateFormat(dateFormat);
request.setLocale(locale);
request.setActivatedOnDate(formattedDate);
- Response<DeleteSavingsAccountsAccountIdResponse> response =
okR(fineractClient().savingsAccounts.delete20(EXTERNAL_ID));
+ Response<DeleteSavingsAccountsAccountIdResponse> response =
okR(fineractClient().savingsAccounts.delete19(EXTERNAL_ID));
assertThat(response.isSuccessful()).isTrue();
assertThat(response.body()).isNotNull();