-
Notifications
You must be signed in to change notification settings - Fork 49
Implement JSON export service for intelligence products (risk, coalition, trends) #8048
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weβll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
c5e35b8
e67d42f
7fbe114
7a307fa
5fc4262
ac4dbfe
82ed6cb
ab2cf9a
e50e9c6
1e75441
65ce937
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,76 @@ | ||
| /* | ||
| * Copyright 2010-2025 James Pether SΓΆrling | ||
| * | ||
| * Licensed 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. | ||
| * | ||
| * $Id$ | ||
| * $HeadURL$ | ||
| */ | ||
| package com.hack23.cia.service.data.api; | ||
|
|
||
| import java.io.IOException; | ||
|
|
||
| /** | ||
| * Service interface for exporting intelligence products as JSON. | ||
| * | ||
| * Provides JSON export capabilities for risk assessments, coalition alignment, | ||
| * and temporal trends to support CDN-ready static file generation and API endpoints. | ||
| * | ||
| * @author intelligence-operative | ||
| * @since v1.36 (Intelligence Products JSON Export) | ||
| */ | ||
| public interface IntelligenceExportService { | ||
|
|
||
| /** | ||
| * Export risk assessment data for all rule violations. | ||
| * | ||
| * Generates JSON containing all 50 risk rules with their current violations, | ||
| * severity levels, and affected entities (politicians, parties, committees, ministries). | ||
| * | ||
| * @return JSON string containing risk assessment data | ||
| * @throws IOException if JSON generation fails | ||
| */ | ||
| String exportRiskAssessments() throws IOException; | ||
|
|
||
| /** | ||
| * Export coalition alignment matrix showing voting alignment between parties. | ||
| * | ||
| * Generates JSON containing pairwise party alignment rates, total votes, | ||
| * and aligned votes for coalition stability analysis. | ||
| * | ||
| * @return JSON string containing coalition alignment matrix | ||
| * @throws IOException if JSON generation fails | ||
| */ | ||
| String exportCoalitionAlignment() throws IOException; | ||
|
|
||
| /** | ||
| * Export temporal trend analysis with daily/weekly/monthly/annual patterns. | ||
| * | ||
| * Generates JSON containing decision volumes, approval rates, moving averages, | ||
| * and year-over-year comparisons for trend forecasting. | ||
| * | ||
| * @return JSON string containing temporal trends data | ||
| * @throws IOException if JSON generation fails | ||
| */ | ||
| String exportTemporalTrends() throws IOException; | ||
|
|
||
| /** | ||
| * Write JSON export to file for CDN deployment. | ||
| * | ||
| * @param jsonContent the JSON content to write | ||
| * @param fileName the file name (e.g., "risk-assessments.json") | ||
| * @param outputDirectory the output directory path | ||
| * @throws IOException if file write fails | ||
| */ | ||
| void writeJsonToFile(String jsonContent, String fileName, String outputDirectory) throws IOException; | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,183 @@ | ||||||||||
| /* | ||||||||||
| * Copyright 2010-2025 James Pether SΓΆrling | ||||||||||
| * | ||||||||||
| * Licensed 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. | ||||||||||
| * | ||||||||||
| * $Id$ | ||||||||||
| * $HeadURL$ | ||||||||||
| */ | ||||||||||
| package com.hack23.cia.service.data.impl; | ||||||||||
|
|
||||||||||
| import java.io.File; | ||||||||||
| import java.io.IOException; | ||||||||||
| import java.nio.charset.StandardCharsets; | ||||||||||
| import java.nio.file.Files; | ||||||||||
| import java.nio.file.Paths; | ||||||||||
| import java.util.Date; | ||||||||||
| import java.util.List; | ||||||||||
|
|
||||||||||
| import org.springframework.beans.factory.annotation.Autowired; | ||||||||||
| import org.springframework.stereotype.Service; | ||||||||||
| import org.springframework.transaction.annotation.Transactional; | ||||||||||
|
|
||||||||||
| import com.fasterxml.jackson.databind.ObjectMapper; | ||||||||||
| import com.fasterxml.jackson.databind.SerializationFeature; | ||||||||||
| import com.hack23.cia.model.internal.application.data.impl.ViewDecisionTemporalTrends; | ||||||||||
| import com.hack23.cia.model.internal.application.data.party.impl.ViewRiksdagenCoalitionAlignmentMatrix; | ||||||||||
| import com.hack23.cia.model.internal.application.data.rules.impl.RuleViolation; | ||||||||||
| import com.hack23.cia.service.data.api.IntelligenceExportService; | ||||||||||
| import com.hack23.cia.service.data.api.RuleViolationDAO; | ||||||||||
| import com.hack23.cia.service.data.api.ViewDecisionTemporalTrendsDAO; | ||||||||||
| import com.hack23.cia.service.data.api.ViewRiksdagenCoalitionAlignmentMatrixDAO; | ||||||||||
| import com.hack23.cia.service.data.impl.export.CoalitionAlignmentExportDTO; | ||||||||||
| import com.hack23.cia.service.data.impl.export.CoalitionAlignmentExportDTO.PartyAlignment; | ||||||||||
| import com.hack23.cia.service.data.impl.export.ExportMetadata; | ||||||||||
| import com.hack23.cia.service.data.impl.export.RiskAssessmentExportDTO; | ||||||||||
| import com.hack23.cia.service.data.impl.export.RiskAssessmentExportDTO.RiskViolation; | ||||||||||
| import com.hack23.cia.service.data.impl.export.TemporalTrendsExportDTO; | ||||||||||
| import com.hack23.cia.service.data.impl.export.TemporalTrendsExportDTO.TrendDataPoint; | ||||||||||
|
|
||||||||||
| /** | ||||||||||
| * Implementation of IntelligenceExportService. | ||||||||||
| * | ||||||||||
| * @author intelligence-operative | ||||||||||
| * @since v1.36 | ||||||||||
| */ | ||||||||||
| @Service | ||||||||||
| @Transactional(readOnly = true) | ||||||||||
| public class IntelligenceExportServiceImpl implements IntelligenceExportService { | ||||||||||
|
||||||||||
| public class IntelligenceExportServiceImpl implements IntelligenceExportService { | |
| final class IntelligenceExportServiceImpl implements IntelligenceExportService { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fc4262. Changed from public class to final class to match codebase conventions.
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ObjectMapper is configured to disable WRITE_DATES_AS_TIMESTAMPS, but Jackson also needs a date format configuration to properly serialize dates as ISO 8601 strings. Without an explicit date format, dates may not serialize consistently.
Consider adding:
this.objectMapper.setDateFormat(new StdDateFormat().withColonInTimeZone(true));This ensures dates are serialized as ISO 8601 strings (e.g., "2024-12-08T11:12:00Z") as described in the PR description.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in ac4dbfe. Added StdDateFormat().withColonInTimeZone(true) configuration to ObjectMapper to ensure dates are serialized as ISO 8601 strings (e.g., "2024-12-08T11:12:00Z").
Check failure on line 84 in service.data.impl/src/main/java/com/hack23/cia/service/data/impl/IntelligenceExportServiceImpl.java
SonarQubeCloud / SonarCloud Code Analysis
Define a constant instead of duplicating this literal "intelligence-schema" 3 times.
See more on https://sonarcloud.io/project/issues?id=Hack23_cia&issues=AZr9qiz8bOiZaeb3GYME&open=AZr9qiz8bOiZaeb3GYME&pullRequest=8048
Outdated
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fully-qualified class name is unnecessary here since RuleViolation is already imported at line 37 and used without FQCN on line 79. This should simply be:
for (final RuleViolation violation : violations) {| for (final com.hack23.cia.model.internal.application.data.rules.impl.RuleViolation violation : violations) { | |
| for (final RuleViolation violation : violations) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fc4262. Removed fully-qualified class name and used the imported RuleViolation directly.
Outdated
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of mkdirs() without checking the return value can lead to silent failures. If directory creation fails (e.g., due to permissions), the subsequent Files.write() will fail. Check the return value and throw an appropriate exception:
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Failed to create directory: " + outputDirectory);
}| if (!directory.exists()) { | |
| directory.mkdirs(); | |
| if (!directory.exists() && !directory.mkdirs()) { | |
| throw new IOException("Failed to create directory: " + outputDirectory); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fc4262. Added check for mkdirs() return value and throw IOException with descriptive message if directory creation fails.
Outdated
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The writeJsonToFile method is vulnerable to path traversal attacks. An attacker could provide a malicious fileName containing path traversal sequences (e.g., ../../etc/passwd) to write files outside the intended directory. Validate and sanitize the fileName parameter to ensure it doesn't contain directory separators or path traversal sequences:
// Validate fileName doesn't contain path separators
if (fileName.contains("/") || fileName.contains("\\") || fileName.contains("..")) {
throw new IllegalArgumentException("Invalid file name: must not contain path separators or traversal sequences");
}There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fc4262. Added validation to reject file names containing /, \, or .. to prevent path traversal attacks. Throws IllegalArgumentException with descriptive message.
Copilot
AI
Dec 8, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The writeJsonToFile method is not covered by unit tests. Add a test case to verify file creation, directory creation, and content writing behavior. Consider testing both scenarios: when the directory exists and when it needs to be created.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in 5fc4262. Added 3 new tests for writeJsonToFile: testWriteJsonToFile (basic functionality), testWriteJsonToFileCreatesDirectory (directory creation), and testWriteJsonToFileRejectsPathTraversal (security validation).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The README states "Unit Tests - Comprehensive tests with Mockito (3/3 passing)" but the test file contains 6 test methods, not 3. This discrepancy should be corrected to accurately reflect the test coverage.
Update to: "Unit Tests - Comprehensive tests with Mockito (6/6 passing)"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed in ac4dbfe. Corrected test count from "3/3 passing" to "6/6 passing" to accurately reflect the actual test coverage.