Skip to content

Commit 41da36b

Browse files
airajenaadamsaghy
authored andcommitted
FINERACT-2028: Add audit logging for manual scheduler job execution
1 parent 296cf90 commit 41da36b

File tree

5 files changed

+141
-1
lines changed

5 files changed

+141
-1
lines changed

fineract-core/src/main/java/org/apache/fineract/commands/service/CommandWrapperBuilder.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2287,6 +2287,14 @@ public CommandWrapperBuilder updateJobDetail(final Long jobId) {
22872287
return this;
22882288
}
22892289

2290+
public CommandWrapperBuilder executeSchedulerJob(final Long jobId) {
2291+
this.actionName = "EXECUTEJOB";
2292+
this.entityName = "SCHEDULER";
2293+
this.entityId = jobId;
2294+
this.href = "/jobs/" + jobId + "?command=executeJob";
2295+
return this;
2296+
}
2297+
22902298
public CommandWrapperBuilder createMeeting(final CommandWrapper resourceDetails, final String supportedEntityType,
22912299
final Long supportedEntityId) {
22922300
this.actionName = "CREATE";

fineract-provider/src/main/java/org/apache/fineract/infrastructure/jobs/api/SchedulerJobApiResource.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,7 +227,11 @@ private Response executeJob(@NotNull IdTypeResolver.IdType idType, String identi
227227
response = Response.status(400).build();
228228
if (is(commandParam, SchedulerJobApiConstants.COMMAND_EXECUTE_JOB)) {
229229
Long jobId = schedulerJobRunnerReadService.retrieveId(idType, identifier);
230-
jobRegisterService.executeJobWithParameters(jobId, jsonRequestBody);
230+
final CommandWrapper commandRequest = new CommandWrapperBuilder() //
231+
.executeSchedulerJob(jobId) //
232+
.withJson(jsonRequestBody) //
233+
.build();
234+
commandsSourceWritePlatformService.logCommandSource(commandRequest);
231235
response = Response.status(202).build();
232236
} else {
233237
throw new UnrecognizedQueryParamException(SchedulerJobApiConstants.COMMAND, commandParam);
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.infrastructure.jobs.handler;
20+
21+
import lombok.RequiredArgsConstructor;
22+
import org.apache.fineract.commands.annotation.CommandType;
23+
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
24+
import org.apache.fineract.infrastructure.core.api.JsonCommand;
25+
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
26+
import org.apache.fineract.infrastructure.core.data.CommandProcessingResultBuilder;
27+
import org.apache.fineract.infrastructure.jobs.service.JobRegisterService;
28+
import org.springframework.stereotype.Service;
29+
30+
@Service
31+
@RequiredArgsConstructor
32+
@CommandType(entity = "SCHEDULER", action = "EXECUTEJOB")
33+
public class ExecuteJobCommandHandler implements NewCommandSourceHandler {
34+
35+
private final JobRegisterService jobRegisterService;
36+
37+
@Override
38+
public CommandProcessingResult processCommand(final JsonCommand command) {
39+
final Long jobId = command.entityId();
40+
jobRegisterService.executeJobWithParameters(jobId, command.json());
41+
return new CommandProcessingResultBuilder() //
42+
.withCommandId(command.commandId()) //
43+
.withEntityId(jobId) //
44+
.build();
45+
}
46+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package org.apache.fineract.infrastructure.jobs.handler;
20+
21+
import static org.junit.jupiter.api.Assertions.assertEquals;
22+
import static org.mockito.Mockito.verify;
23+
import static org.mockito.Mockito.when;
24+
25+
import org.apache.fineract.infrastructure.core.api.JsonCommand;
26+
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
27+
import org.apache.fineract.infrastructure.jobs.service.JobRegisterService;
28+
import org.junit.jupiter.api.Test;
29+
import org.junit.jupiter.api.extension.ExtendWith;
30+
import org.mockito.InjectMocks;
31+
import org.mockito.Mock;
32+
import org.mockito.junit.jupiter.MockitoExtension;
33+
34+
@ExtendWith(MockitoExtension.class)
35+
class ExecuteJobCommandHandlerTest {
36+
37+
@Mock
38+
private JobRegisterService jobRegisterService;
39+
40+
@Mock
41+
private JsonCommand command;
42+
43+
@InjectMocks
44+
private ExecuteJobCommandHandler underTest;
45+
46+
@Test
47+
void shouldExecuteJobAndReturnCommandResult() {
48+
// given
49+
Long jobId = 123L;
50+
Long commandId = 456L;
51+
String json = "{\"includeTasks\":true}";
52+
when(command.entityId()).thenReturn(jobId);
53+
when(command.commandId()).thenReturn(commandId);
54+
when(command.json()).thenReturn(json);
55+
56+
// when
57+
CommandProcessingResult result = underTest.processCommand(command);
58+
59+
// then
60+
verify(jobRegisterService).executeJobWithParameters(jobId, json);
61+
assertEquals(commandId, result.getCommandId());
62+
assertEquals(jobId, result.getResourceId());
63+
}
64+
}

integration-tests/src/test/java/org/apache/fineract/integrationtests/AuditIntegrationTest.java

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.apache.fineract.integrationtests.common.AuditHelper;
3737
import org.apache.fineract.integrationtests.common.ClientHelper;
3838
import org.apache.fineract.integrationtests.common.OfficeHelper;
39+
import org.apache.fineract.integrationtests.common.SchedulerJobHelper;
3940
import org.apache.fineract.integrationtests.common.Utils;
4041
import org.junit.jupiter.api.BeforeEach;
4142
import org.junit.jupiter.api.Test;
@@ -51,6 +52,7 @@ public class AuditIntegrationTest {
5152
private RequestSpecification requestSpec;
5253
private ClientHelper clientHelper;
5354
private AuditHelper auditHelper;
55+
private SchedulerJobHelper schedulerJobHelper;
5456
private static final SecureRandom rand = new SecureRandom();
5557

5658
/**
@@ -65,6 +67,7 @@ public void setup() {
6567
this.responseSpec = new ResponseSpecBuilder().expectStatusCode(200).build();
6668
this.auditHelper = new AuditHelper(this.requestSpec, this.responseSpec);
6769
this.clientHelper = new ClientHelper(this.requestSpec, this.responseSpec);
70+
this.schedulerJobHelper = new SchedulerJobHelper(this.requestSpec);
6871
}
6972

7073
@Test
@@ -157,4 +160,19 @@ public void checkIfOrderBySupported() {
157160

158161
}
159162

163+
@SuppressWarnings("unchecked")
164+
@Test
165+
public void executeSchedulerJobShouldCreateAuditEntry() {
166+
// given
167+
int jobId = schedulerJobHelper.getSchedulerJobIdByShortName("SA_AANF");
168+
List<HashMap<String, Object>> auditsRecievedInitial = auditHelper.getAuditDetails(jobId, "EXECUTEJOB", "SCHEDULER");
169+
170+
// when
171+
schedulerJobHelper.runSchedulerJob(jobId);
172+
173+
// then
174+
List<HashMap<String, Object>> auditsRecieved = auditHelper.getAuditDetails(jobId, "EXECUTEJOB", "SCHEDULER");
175+
auditHelper.verifyMultipleAuditsOnserver(auditsRecievedInitial, auditsRecieved, jobId, "EXECUTEJOB", "SCHEDULER");
176+
}
177+
160178
}

0 commit comments

Comments
 (0)