Filter for instances read, write, batch
This commit is contained in:
committed by
Arnold Gálovics
parent
ee1f988be6
commit
ebf0e8b539
+20
@@ -60,5 +60,25 @@ public class FineractProperties {
|
||||
public boolean isReadOnlyMode() {
|
||||
return readEnabled && !writeEnabled && !batchEnabled;
|
||||
}
|
||||
|
||||
public boolean isWriteOnlyMode() {
|
||||
return !readEnabled && writeEnabled && !batchEnabled;
|
||||
}
|
||||
|
||||
public boolean isBatchOnlyMode() {
|
||||
return !readEnabled && !writeEnabled && batchEnabled;
|
||||
}
|
||||
|
||||
public boolean isReadInstance() {
|
||||
return isReadOnlyMode() || readEnabled;
|
||||
}
|
||||
|
||||
public boolean isWriteInstance() {
|
||||
return isWriteOnlyMode() || writeEnabled;
|
||||
}
|
||||
|
||||
public boolean isBatchInstance() {
|
||||
return isBatchOnlyMode() || batchEnabled;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-1
@@ -19,6 +19,7 @@
|
||||
|
||||
package org.apache.fineract.infrastructure.core.config;
|
||||
|
||||
import org.apache.fineract.infrastructure.security.filter.FineractInstanceModeApiFilter;
|
||||
import org.apache.fineract.infrastructure.security.filter.TenantAwareBasicAuthenticationFilter;
|
||||
import org.apache.fineract.infrastructure.security.filter.TwoFactorAuthenticationFilter;
|
||||
import org.apache.fineract.infrastructure.security.service.TenantAwareJpaPlatformUserDetailsService;
|
||||
@@ -53,6 +54,12 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
@Autowired
|
||||
private TwoFactorAuthenticationFilter twoFactorAuthenticationFilter;
|
||||
|
||||
@Autowired
|
||||
private FineractInstanceModeApiFilter fineractInstanceModeApiFilter;
|
||||
|
||||
@Autowired
|
||||
private FineractProperties fineractProperties;
|
||||
|
||||
@Autowired
|
||||
private ServerProperties serverProperties;
|
||||
|
||||
@@ -77,7 +84,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
.sessionManagement() //
|
||||
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) //
|
||||
.and() //
|
||||
.addFilterAfter(tenantAwareBasicAuthenticationFilter(), SecurityContextPersistenceFilter.class) //
|
||||
.addFilterAfter(fineractInstanceModeApiFilter, SecurityContextPersistenceFilter.class) //
|
||||
.addFilterAfter(tenantAwareBasicAuthenticationFilter(), FineractInstanceModeApiFilter.class) //
|
||||
.addFilterAfter(twoFactorAuthenticationFilter, BasicAuthenticationFilter.class); //
|
||||
|
||||
if (serverProperties.getSsl().isEnabled()) {
|
||||
|
||||
+19
-4
@@ -19,8 +19,10 @@
|
||||
package org.apache.fineract.infrastructure.core.data;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.google.gson.Gson;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -72,7 +74,17 @@ public class ApiGlobalErrorResponse {
|
||||
globalErrorResponse.setHttpStatusCode("401");
|
||||
globalErrorResponse.setDeveloperMessage("Invalid tenant details were passed in api request.");
|
||||
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.invalid.tenant.identifier");
|
||||
globalErrorResponse.setDefaultUserMessage("Invalide tenant identifier provided with request.");
|
||||
globalErrorResponse.setDefaultUserMessage("Invalid tenant identifier provided with request.");
|
||||
|
||||
return globalErrorResponse;
|
||||
}
|
||||
|
||||
public static ApiGlobalErrorResponse invalidInstanceTypeMethod(final String method) {
|
||||
final ApiGlobalErrorResponse globalErrorResponse = new ApiGlobalErrorResponse();
|
||||
globalErrorResponse.setHttpStatusCode(Status.METHOD_NOT_ALLOWED.toString());
|
||||
globalErrorResponse.setDeveloperMessage("Invalid instance type called in api request for the method " + method);
|
||||
globalErrorResponse.setUserMessageGlobalisationCode("error.msg.invalid.instance.type");
|
||||
globalErrorResponse.setDefaultUserMessage("Invalid method " + method + " used with request to this instance type.");
|
||||
|
||||
return globalErrorResponse;
|
||||
}
|
||||
@@ -186,9 +198,7 @@ public class ApiGlobalErrorResponse {
|
||||
return globalErrorResponse;
|
||||
}
|
||||
|
||||
protected ApiGlobalErrorResponse() {
|
||||
//
|
||||
}
|
||||
protected ApiGlobalErrorResponse() {}
|
||||
|
||||
public ApiGlobalErrorResponse(final List<ApiParameterError> errors) {
|
||||
this.errors = errors;
|
||||
@@ -234,4 +244,9 @@ public class ApiGlobalErrorResponse {
|
||||
public void setUserMessageGlobalisationCode(final String userMessageGlobalisationCode) {
|
||||
this.userMessageGlobalisationCode = userMessageGlobalisationCode;
|
||||
}
|
||||
|
||||
public String toJson() {
|
||||
final Gson gson = new Gson();
|
||||
return gson.toJson(this);
|
||||
}
|
||||
}
|
||||
|
||||
+23
-26
@@ -39,12 +39,16 @@ import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.Context;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
import javax.ws.rs.core.UriInfo;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.config.FineractProperties;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.exception.UnrecognizedQueryParamException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
@@ -57,13 +61,13 @@ import org.apache.fineract.infrastructure.jobs.service.JobRegisterService;
|
||||
import org.apache.fineract.infrastructure.jobs.service.SchedulerJobRunnerReadService;
|
||||
import org.apache.fineract.infrastructure.security.exception.NoAuthorizationException;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/jobs")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
@Tag(name = "MIFOSX-BATCH JOBS", description = "Batch jobs (also known as cron jobs on Unix-based systems) are a series of back-end jobs executed on a computer at a particular time defined in job's cron expression.\n\n At any point, you can view the list of batch jobs scheduled to run along with other details specific to each job. Manually you can execute the jobs at any point of time.\n\n The scheduler status can be either \"Active\" or \"Standby\". If the scheduler status is Active, it indicates that all batch jobs are running/ will run as per the specified schedule.If the scheduler status is Standby, it will ensure all scheduled batch runs are suspended.")
|
||||
public class SchedulerJobApiResource {
|
||||
|
||||
@@ -74,21 +78,7 @@ public class SchedulerJobApiResource {
|
||||
private final ToApiJsonSerializer<JobDetailHistoryData> jobHistoryToApiJsonSerializer;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
private final PlatformSecurityContext context;
|
||||
|
||||
@Autowired
|
||||
public SchedulerJobApiResource(final SchedulerJobRunnerReadService schedulerJobRunnerReadService,
|
||||
final JobRegisterService jobRegisterService, final ToApiJsonSerializer<JobDetailData> toApiJsonSerializer,
|
||||
final ApiRequestParameterHelper apiRequestParameterHelper,
|
||||
final ToApiJsonSerializer<JobDetailHistoryData> jobHistoryToApiJsonSerializer,
|
||||
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, final PlatformSecurityContext context) {
|
||||
this.schedulerJobRunnerReadService = schedulerJobRunnerReadService;
|
||||
this.jobRegisterService = jobRegisterService;
|
||||
this.toApiJsonSerializer = toApiJsonSerializer;
|
||||
this.jobHistoryToApiJsonSerializer = jobHistoryToApiJsonSerializer;
|
||||
this.apiRequestParameterHelper = apiRequestParameterHelper;
|
||||
this.commandsSourceWritePlatformService = commandsSourceWritePlatformService;
|
||||
this.context = context;
|
||||
}
|
||||
private final FineractProperties fineractProperties;
|
||||
|
||||
@GET
|
||||
@Operation(summary = "Retrieve Scheduler Jobs", description = "Returns the list of jobs.\n" + "\n" + "Example Requests:\n" + "\n"
|
||||
@@ -142,17 +132,24 @@ public class SchedulerJobApiResource {
|
||||
public Response executeJob(@PathParam(SchedulerJobApiConstants.JOB_ID) @Parameter(description = "jobId") final Long jobId,
|
||||
@QueryParam(SchedulerJobApiConstants.COMMAND) @Parameter(description = "command") final String commandParam) {
|
||||
// check the logged in user have permissions to execute scheduler jobs
|
||||
final boolean hasNotPermission = this.context.authenticatedUser().hasNotPermissionForAnyOf("ALL_FUNCTIONS", "EXECUTEJOB_SCHEDULER");
|
||||
if (hasNotPermission) {
|
||||
final String authorizationMessage = "User has no authority to execute scheduler jobs";
|
||||
throw new NoAuthorizationException(authorizationMessage);
|
||||
}
|
||||
Response response = Response.status(400).build();
|
||||
if (is(commandParam, SchedulerJobApiConstants.COMMAND_EXECUTE_JOB)) {
|
||||
this.jobRegisterService.executeJob(jobId);
|
||||
response = Response.status(202).build();
|
||||
Response response;
|
||||
if (fineractProperties.getMode().isBatchInstance()) {
|
||||
final boolean hasNotPermission = this.context.authenticatedUser().hasNotPermissionForAnyOf("ALL_FUNCTIONS",
|
||||
"EXECUTEJOB_SCHEDULER");
|
||||
if (hasNotPermission) {
|
||||
final String authorizationMessage = "User has no authority to execute scheduler jobs";
|
||||
throw new NoAuthorizationException(authorizationMessage);
|
||||
}
|
||||
response = Response.status(400).build();
|
||||
if (is(commandParam, SchedulerJobApiConstants.COMMAND_EXECUTE_JOB)) {
|
||||
this.jobRegisterService.executeJob(jobId);
|
||||
response = Response.status(202).build();
|
||||
} else {
|
||||
throw new UnrecognizedQueryParamException(SchedulerJobApiConstants.COMMAND, commandParam);
|
||||
}
|
||||
} else {
|
||||
throw new UnrecognizedQueryParamException(SchedulerJobApiConstants.COMMAND, commandParam);
|
||||
ApiGlobalErrorResponse errorResponse = ApiGlobalErrorResponse.invalidInstanceTypeMethod("Batch");
|
||||
response = Response.status(Status.METHOD_NOT_ALLOWED).entity(errorResponse).build();
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
+4
@@ -97,6 +97,10 @@ public class JobRegisterServiceImpl implements JobRegisterService, ApplicationLi
|
||||
|
||||
@PostConstruct
|
||||
public void loadAllJobs() {
|
||||
// If the instance is not Batch Enabled will not load the Jobs
|
||||
if (!fineractProperties.getMode().isBatchEnabled()) {
|
||||
return;
|
||||
}
|
||||
final List<FineractPlatformTenant> allTenants = this.tenantDetailsService.findAllTenants();
|
||||
for (final FineractPlatformTenant tenant : allTenants) {
|
||||
ThreadLocalContextUtil.setTenant(tenant);
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* 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.infrastructure.security.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link RuntimeException} thrown when an invalid method in the Fineract instance type called in request to platform.
|
||||
*
|
||||
*
|
||||
*/
|
||||
public class InvalidInstanceTypeMethodException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public InvalidInstanceTypeMethodException(final String method) {
|
||||
super("error.msg.invalid.method.for.instance.type", "Method Not Allowed " + method + " for the instance type");
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* 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.infrastructure.security.filter;
|
||||
|
||||
import java.io.IOException;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.ws.rs.HttpMethod;
|
||||
import javax.ws.rs.ext.Provider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.infrastructure.core.config.FineractProperties;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiGlobalErrorResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.web.filter.OncePerRequestFilter;
|
||||
|
||||
@Provider
|
||||
@Component
|
||||
@RequiredArgsConstructor
|
||||
public class FineractInstanceModeApiFilter extends OncePerRequestFilter {
|
||||
|
||||
private final FineractProperties fineractProperties;
|
||||
|
||||
@Override
|
||||
protected void doFilterInternal(final HttpServletRequest request, final HttpServletResponse response, final FilterChain filterChain)
|
||||
throws ServletException, IOException {
|
||||
|
||||
if (fineractProperties.getMode().isReadInstance() && isReadMethod(request)) {
|
||||
filterChain.doFilter(request, response);
|
||||
} else if (fineractProperties.getMode().isWriteInstance()) {
|
||||
filterChain.doFilter(request, response);
|
||||
} else if (fineractProperties.getMode().isBatchInstance() && request.getPathInfo().startsWith("/jobs")) {
|
||||
filterChain.doFilter(request, response);
|
||||
} else {
|
||||
response.setStatus(HttpStatus.SC_METHOD_NOT_ALLOWED);
|
||||
ApiGlobalErrorResponse errorResponse = ApiGlobalErrorResponse.invalidInstanceTypeMethod(request.getMethod());
|
||||
response.getWriter().write(errorResponse.toJson());
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isReadMethod(HttpServletRequest request) {
|
||||
return HttpMethod.GET.equals(request.getMethod());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user