-
Notifications
You must be signed in to change notification settings - Fork 214
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
Feature/json validation #1700
Feature/json validation #1700
Conversation
WalkthroughThis pull request updates the monitor configuration on the server by adding three new fields— Changes
Sequence Diagram(s)sequenceDiagram
participant Job as Job Data
participant NS as NetworkService
participant HTTP as HTTP Service
participant Validator as Response Validator
Job->>NS: Submit job with monitor details (url, jsonPath, expectedValue, matchMethod)
NS->>HTTP: Execute HTTP request using provided URL
HTTP-->>NS: Return HTTP response
alt expectedValue provided
NS->>Validator: Extract value using jsonPath
Validator-->>NS: Return extracted value
NS->>NS: Validate extracted value using matchMethod vs expectedValue
end
NS-->>Job: Return response status and message
Possibly related PRs
Suggested reviewers
✨ Finishing Touches
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
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.
Actionable comments posted: 3
🧹 Nitpick comments (3)
Server/service/networkService.js (2)
126-126
: Enhance readability with explicit conditionalUsing
&&
for conditional assignment can be less clear to readers. Consider using an explicitif
statement for better readability and maintainability.Apply this diff:
- secret !== undefined && (config.headers = { Authorization: `Bearer ${secret}` }); + if (secret !== undefined) { + config.headers = { Authorization: `Bearer ${secret}` }; + }
164-164
: Simplify content type check with optional chainingYou can make the content type check more concise using optional chaining.
Apply this diff:
- if (contentType && contentType.includes('application/json')) { + if (contentType?.includes('application/json')) {🧰 Tools
🪛 Biome (1.9.4)
[error] 164-164: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
Server/db/models/Monitor.js (1)
41-54
: Consider adding validation constraints to new schema fieldsThe fields
jsonPath
,expectedValue
, andmatchMethod
currently lack validation constraints. To ensure data integrity, consider adding validations such as required fields or default values.
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
Server/package-lock.json
is excluded by!**/package-lock.json
📒 Files selected for processing (4)
Server/db/models/Monitor.js
(1 hunks)Server/package.json
(1 hunks)Server/service/networkService.js
(3 hunks)Server/validation/joi.js
(2 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
Server/service/networkService.js
[error] 164-164: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (4)
Server/service/networkService.js (3)
133-136
: Inclusion of additional response fields is appropriateAdding
monitorId
,teamId
, andtype
to thehttpResponse
object enhances the context and is a good practice.
1-1
:⚠️ Potential issueVerify the use of
jmespath
for JSONPath functionalityIt appears that
jmespath
is imported to handle JSONPath queries. However,jmespath
and JSONPath are distinct query languages with different syntax. Please verify thatjmespath
meets your requirements, or consider using a library likejsonpath
that specifically supports JSONPath.
161-172
:⚠️ Potential issueEnsure compatibility between
jsonPath
andjmespath
You're using
jmespath.search()
with ajsonPath
expression. Sincejmespath
and JSONPath have different syntaxes, verify that thejsonPath
provided is compatible withjmespath
, or adjust the implementation accordingly.🧰 Tools
🪛 Biome (1.9.4)
[error] 164-164: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
Server/package.json (1)
29-29
: Addition of "jmespath" DependencyThe inclusion of
"jmespath": "^0.16.0"
supports the new JSONPath functionality needed for JSON validation as described in the PR objectives. This change aligns with the overall goal of enhancing JSON processing. Keep an eye on the package’s release notes to ensure there aren’t any emerging vulnerabilities that could make your palms sweaty, just like those mom’s spaghetti moments!
Server/service/networkService.js
Outdated
result = result.toString(); | ||
if (matchMethod === "include") match = result.includes(expectedValue); |
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.
🛠️ Refactor suggestion
Improve result string conversion for accurate matching
Using result.toString()
might not yield meaningful results if result
is an object. Consider using JSON.stringify(result)
to convert objects to a JSON string for accurate comparison.
Apply this diff:
- result = result.toString();
+ result = typeof result === 'object' ? JSON.stringify(result) : result.toString();
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
result = result.toString(); | |
if (matchMethod === "include") match = result.includes(expectedValue); | |
result = typeof result === 'object' ? JSON.stringify(result) : result.toString(); | |
if (matchMethod === "include") match = result.includes(expectedValue); |
jsonPath: joi.string(), | ||
expectedValue: joi.string(), | ||
matchMethod: joi.string(), |
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.
Add enumeration validation for matchMethod
in edit monitor validation
Ensure consistency by adding the same enumeration constraints to matchMethod
in the edit validation schema.
Apply this diff:
matchMethod: joi.string(),
+ matchMethod: joi.string().valid('equal', 'include', 'regex'),
Committable suggestion skipped: line range outside the PR's diff.
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.
same here, worth addding this to the validation
jsonPath: joi.string(), | ||
expectedValue: joi.string(), | ||
matchMethod: joi.string(), |
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.
Add enumeration validation for matchMethod
in create monitor validation
To ensure only valid match methods are accepted, add enumeration constraints to the matchMethod
field.
Apply this diff:
matchMethod: joi.string(),
+ matchMethod: joi.string().valid('equal', 'include', 'regex'),
Committable suggestion skipped: line range outside the PR's diff.
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.
This is worth doing
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.
Auto Pull Request Review from LlamaPReview
1. Overview
1.1 PR Summary
- Business value and requirements alignment: This PR introduces JSON validation and matching capabilities using JSONPath, enhancing the HTTP monitoring functionality of the Checkmate tool. This aligns with the need for more robust and flexible monitoring features.
- Key components modified:
Server/db/models/Monitor.js
: Added fields for JSON validation.Server/service/networkService.js
: Implemented JSON validation logic.Server/validation/joi.js
: Updated validation schemas.Server/package.json
: Addedjmespath
dependency.
- Impact assessment: The changes significantly enhance HTTP monitoring by allowing JSON response validation based on JSONPath expressions. This will improve the tool's ability to detect and respond to specific conditions in monitored endpoints.
- System dependencies and integration impacts: The introduction of
jmespath
for JSONPath processing adds a new dependency and potential performance considerations. The removal of thedistributed_http
monitor type requires careful review to ensure no regression in functionality.
1.2 Architecture Changes
- System design modifications: The PR extends the Monitor model to include fields for JSONPath, expected value, and match method. It modifies the
networkService
to incorporate JSON validation logic within HTTP request processing. - Component interactions: The
networkService
now interacts with thejmespath
library to process JSONPath expressions and validate HTTP responses. - Integration points: The JSON validation logic is integrated into the existing HTTP monitoring workflow, affecting how HTTP responses are processed and validated.
2. Detailed Technical Analysis
2.1 Code Logic Deep-Dive
Core Logic Changes
- Server/service/networkService.js - requestHttp
- Submitted PR Code:
if (expectedValue) {
// validate if response data match expected value
let result = response?.data;
this.logger.info({
service: this.SERVICE_NAME,
method: "requestHttp",
message: `Job: [${name}](${_id}) match result with expected value`,
details: { expectedValue, result, jsonPath, matchMethod }
});
if (jsonPath) {
const contentType = response.headers['content-type'];
if (contentType && contentType.includes('application/json')) {
try {
result = jmespath.search(result, jsonPath);
} catch (error) {
httpResponse.status = false;
httpResponse.message = "JSONPath Search Error";
return httpResponse;
}
} else {
httpResponse.status = false;
httpResponse.message = "Response Not JSON";
return httpResponse;
}
}
if (result === null || result === undefined) {
httpResponse.status = false;
httpResponse.message = "Empty Result";
return httpResponse;
}
let match;
result = result.toString();
if (matchMethod === "include") match = result.includes(expectedValue);
else if (matchMethod === "regex") match = new RegExp(expectedValue).test(result);
else match = result === expectedValue;
httpResponse.status = match;
httpResponse.message = match ? "Match" : "Not Match";
return httpResponse;
}
- Analysis:
- The current logic checks for
expectedValue
first. If it exists, it proceeds with validation. However, ifexpectedValue
is provided but the response is not JSON andjsonPath
is not provided, the code still attempts to validateresponse?.data
. This could lead to unexpected behavior becauseresponse?.data
might be undefined or not a stringifiable value in non-JSON responses, yetresult.toString()
is unconditionally called before matching. - Furthermore, the code assumes that if
jsonPath
is not provided, the entireresponse?.data
should be treated as the value to be matched. This might be valid for simple cases, but it's not explicitly documented or handled robustly for non-JSON responses. - The
toString()
conversion ofresult
before matching might not be appropriate for all types of data extracted by JSONPath. For example, if JSONPath extracts a number or boolean, converting it to a string for comparison might lead to type mismatch issues or incorrect matching behavior, especially for "equal" match method.
- The current logic checks for
- LlamaPReview Suggested Improvements:
if (expectedValue) {
// validate if response data match expected value
let result = response?.data;
this.logger.info({
service: this.SERVICE_NAME,
method: "requestHttp",
message: `Job: [${name}](${_id}) match result with expected value`,
details: { expectedValue, result, jsonPath, matchMethod }
});
if (jsonPath) {
const contentType = response.headers['content-type'];
if (contentType && contentType.includes('application/json')) {
try {
result = jmespath.search(result, jsonPath);
} catch (error) {
httpResponse.status = false;
httpResponse.message = "JSONPath Search Error";
return httpResponse;
}
} else {
httpResponse.status = false;
httpResponse.message = "Response Not JSON";
return httpResponse;
}
} else if (response && response.headers && response.headers['content-type'] && !response.headers['content-type'].includes('application/json')) {
// Handle non-JSON response when jsonPath is not provided but expectedValue is.
result = response.data; // Or response.data.toString() if you expect string conversion for non-JSON
}
if (result === null || result === undefined) {
httpResponse.status = false;
httpResponse.message = "Empty Result";
return httpResponse;
}
let match;
const resultValue = typeof result === 'string' ? result : String(result); // Ensure string conversion for matching, but be mindful of potential issues. Consider type-aware comparison if needed.
if (matchMethod === "include") match = resultValue.includes(expectedValue);
else if (matchMethod === "regex") match = new RegExp(expectedValue).test(resultValue);
else match = resultValue === expectedValue;
httpResponse.status = match;
httpResponse.message = match ? "Match" : "Not Match";
return httpResponse;
}
- Improvement rationale:
- Technical benefits: Addresses potential issues with non-JSON responses when
expectedValue
is provided withoutjsonPath
. Adds explicit handling for non-JSON content whenjsonPath
is absent, making the logic more robust. TheresultValue
ensures string conversion for comparison while acknowledging potential type-related issues and suggesting consideration for type-aware comparisons if needed for future enhancements. - Business value: Improves the reliability of HTTP monitoring by handling a wider range of response types and validation scenarios, reducing false negatives or positives.
- Risk assessment: Reduces the risk of unexpected errors or incorrect validation results when dealing with different content types. By explicitly handling non-JSON responses, the system becomes more predictable and maintainable.
- Technical benefits: Addresses potential issues with non-JSON responses when
Core Logic Changes
- Server/service/networkService.js - requestHttp
- Submitted PR Code:
if (result === null || result === undefined) {
httpResponse.status = false;
httpResponse.message = "Empty Result";
return httpResponse;
}
let match;
result = result.toString();
if (matchMethod === "include") match = result.includes(expectedValue);
else if (matchMethod === "regex") match = new RegExp(expectedValue).test(result);
else match = result === expectedValue;
httpResponse.status = match;
httpResponse.message = match ? "Match" : "Not Match";
return httpResponse;
}
- Analysis:
- The current logic uses a simple string conversion
result.toString()
for all match methods ("include", "regex", "equal"). This might lead to incorrect comparisons, especially for non-stringexpectedValue
. For instance, ifexpectedValue
is intended to be a number but is passed as a string, the "equal" comparison will be string-based, not number-based. This is a potential logical error. - Furthermore, the regex match
new RegExp(expectedValue).test(result)
is vulnerable to regular expression injection ifexpectedValue
is not properly sanitized. Although the context is internal monitoring configuration, it's still a good practice to consider sanitization or use safer regex matching methods if external input is ever incorporated intoexpectedValue
. The initial review already mentioned JSONPath injection, but regex injection is another related security concern introduced by thematchMethod: regex
.
- The current logic uses a simple string conversion
- LlamaPReview Suggested Improvements:
if (result === null || result === undefined) {
httpResponse.status = false;
httpResponse.message = "Empty Result";
return httpResponse;
}
let match;
let resultValue = result; // Keep original type for 'equal' comparison
if (matchMethod === "include") {
resultValue = String(result); // Convert to string only for 'include' and 'regex' if needed
match = resultValue.includes(expectedValue);
} else if (matchMethod === "regex") {
resultValue = String(result); // Convert to string for regex test
try {
match = new RegExp(expectedValue).test(resultValue); // Consider sanitizing expectedValue for regex injection
} catch (regexError) {
httpResponse.status = false;
httpResponse.message = "Regex Compilation Error"; // Handle invalid regex patterns
return httpResponse;
}
} else { // matchMethod === "equal"
match = resultValue == expectedValue; // Use loose equality for 'equal' to handle type coercion if needed, or strict equality '===' for type-sensitive comparison. Original code used strict equality after toString() conversion, which is not ideal.
}
httpResponse.status = match;
httpResponse.message = match ? "Match" : "Not Match";
return httpResponse;
}
- Improvement rationale:
- Technical benefits: Improves the accuracy of matching by preserving the original type of
result
for "equal" comparison and only converting to string when necessary for "include" and "regex". Adds error handling for regex compilation to prevent crashes due to invalid regex patterns. Addresses potential regex injection by highlighting the need for sanitization. - Business value: Ensures more reliable and accurate monitoring results, reducing false alarms caused by incorrect type comparisons or regex errors.
- Risk assessment: Mitigates the risk of incorrect matching due to type mismatches and adds robustness against invalid regex patterns. Raises awareness of regex injection vulnerability, prompting further security considerations. The use of
try-catch
for regex compilation is a crucial improvement for error handling. Using loose equality==
for "equal" match is a design choice to allow for type coercion, which might be beneficial in some use cases, but strict equality===
could also be considered for more type-sensitive comparisons, depending on the desired behavior.
- Technical benefits: Improves the accuracy of matching by preserving the original type of
2.2 Implementation Quality
- Code organization and structure: The PR is well-organized, with changes localized to relevant files. The addition of new fields and validation logic is clear and follows existing patterns.
- Design patterns usage: The use of JSONPath for validation is a good design choice, leveraging a well-known standard for querying JSON data.
- Error handling approach: The PR includes basic error handling for JSONPath search errors and empty results. However, additional error handling for regex compilation errors and non-JSON responses is suggested.
- Resource management: The PR does not introduce significant new resources but adds a dependency on
jmespath
, which should be managed carefully.
3. Critical Findings
3.1 Potential Issues
-
🔴 Critical Issues
- Potential JSONPath injection vulnerability: The
jsonPath
input should be properly sanitized to prevent JSONPath injection attacks.- Impact: Could lead to security vulnerabilities if
jsonPath
is not properly sanitized. - Recommendation: Implement sanitization for
jsonPath
input to prevent injection attacks.
- Impact: Could lead to security vulnerabilities if
- Performance impact of
jmespath
processing: The use ofjmespath
for JSONPath processing may introduce performance overhead, especially with complex paths and large JSON payloads.- Impact: Could degrade the performance of the monitoring service.
- Recommendation: Assess
jmespath
performance under load and implement performance tests if necessary.
- Increased complexity in
requestHttp
function: The added complexity in therequestHttp
function may introduce bugs and maintainability challenges.- Impact: Increased risk of bugs and difficulties in maintaining the code.
- Recommendation: Ensure thorough testing and consider refactoring for better maintainability.
- Unintended removal of
distributed_http
functionality: The removal of thedistributed_http
monitor type could be a regression.- Impact: Loss of functionality for distributed HTTP monitoring.
- Recommendation: Confirm if the removal is intentional and understand the rationale/impact.
- Potential JSONPath injection vulnerability: The
-
🟡 Warnings
- Potential regex injection vulnerability: The regex match method is vulnerable to regular expression injection if
expectedValue
is not properly sanitized.- Potential risks: Could lead to security vulnerabilities if
expectedValue
is not properly sanitized. - Suggested improvements: Implement sanitization for
expectedValue
to prevent regex injection attacks.
- Potential risks: Could lead to security vulnerabilities if
- Incorrect type comparisons: The current logic uses string conversion for all match methods, which might lead to incorrect comparisons.
- Potential risks: Incorrect monitoring results due to type mismatches.
- Suggested improvements: Preserve the original type of
result
for "equal" comparison and only convert to string when necessary for "include" and "regex".
- Potential regex injection vulnerability: The regex match method is vulnerable to regular expression injection if
3.2 Code Quality Concerns
- Maintainability aspects: The added complexity in the
requestHttp
function may introduce maintainability challenges. - Readability issues: The current logic for matching methods could be clearer with better handling of different data types.
- Performance bottlenecks: The use of
jmespath
for JSONPath processing may introduce performance overhead.
4. Security Assessment
- Authentication/Authorization impacts: No direct impacts on authentication or authorization.
- Data handling concerns: Potential JSONPath and regex injection vulnerabilities need careful review.
- Input validation: Ensure proper sanitization of
jsonPath
andexpectedValue
inputs to prevent injection attacks. - Security best practices: Follow best practices for input validation and sanitization.
- Potential security risks: JSONPath and regex injection vulnerabilities.
- Mitigation strategies: Implement sanitization for
jsonPath
andexpectedValue
inputs. - Security testing requirements: Include tests for JSONPath and regex injection vulnerabilities.
5. Testing Strategy
5.1 Test Coverage
- Unit test analysis: Ensure unit tests cover various JSONPath expressions, match methods, and error scenarios.
- Integration test requirements: Implement integration tests for end-to-end JSON validation workflow.
- Edge cases coverage: Include tests for non-JSON responses, empty results, and invalid regex patterns.
5.2 Test Recommendations
Suggested Test Cases
// Example unit test for JSONPath validation
it('should validate JSONPath and match expected value', async () => {
const job = {
data: {
url: 'http://example.com',
secret: 'secret',
_id: '123',
name: 'Test Job',
teamId: 'team1',
type: 'http',
jsonPath: 'data.value',
matchMethod: 'equal',
expectedValue: 'expected'
}
};
const response = {
data: { data: { value: 'expected' } },
headers: { 'content-type': 'application/json' }
};
const networkService = new NetworkService(axios, ping, logger, http, Docker, net);
const result = await networkService.requestHttp(job, response);
expect(result.status).toBe(true);
expect(result.message).toBe('Match');
});
// Example unit test for regex match method
it('should handle regex match method with sanitized input', async () => {
const job = {
data: {
url: 'http://example.com',
secret: 'secret',
_id: '123',
name: 'Test Job',
teamId: 'team1',
type: 'http',
jsonPath: 'data.value',
matchMethod: 'regex',
expectedValue: '^ex.*$'
}
};
const response = {
data: { data: { value: 'expected' } },
headers: { 'content-type': 'application/json' }
};
const networkService = new NetworkService(axios, ping, logger, http, Docker, net);
const result = await networkService.requestHttp(job, response);
expect(result.status).toBe(true);
expect(result.message).toBe('Match');
});
- Coverage improvements: Ensure coverage for all match methods, JSONPath expressions, and error scenarios.
- Performance testing needs: Assess
jmespath
performance under load and implement performance tests if necessary.
6. Documentation & Maintenance
- Documentation updates needed: Update API and architecture documentation to reflect the new JSON validation capabilities.
- Long-term maintenance considerations: Monitor the performance of
jmespath
processing and address any maintainability challenges in therequestHttp
function. - Technical debt and monitoring requirements: Keep an eye on the complexity introduced by the new validation logic and address any technical debt that arises.
7. Deployment & Operations
- Deployment impact and strategy: Ensure the new dependency
jmespath
is included in the deployment package. Monitor the performance of the monitoring service post-deployment. - Key operational considerations: Be aware of the potential performance impact of
jmespath
processing and monitor the system accordingly.
8. Summary & Recommendations
8.1 Key Action Items
- Implement sanitization for
jsonPath
andexpectedValue
inputs to prevent injection attacks. - Assess
jmespath
performance under load and implement performance tests if necessary. - Ensure thorough testing of the new validation logic, covering all match methods, JSONPath expressions, and error scenarios.
- Confirm if the removal of the
distributed_http
monitor type is intentional and understand the rationale/impact.
8.2 Future Considerations
- Technical evolution path: Continuously monitor the performance and maintainability of the new validation logic.
- Business capability evolution: Consider extending the JSON validation capabilities to other monitoring types if beneficial.
- System integration impacts: Ensure the new validation logic integrates smoothly with existing monitoring workflows and does not introduce regressions.
💡 Help Shape LlamaPReview
How's this review format working for you? Vote in our Github Discussion Polls to help us improve your review experience!
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.
Actionable comments posted: 0
🧹 Nitpick comments (3)
Server/service/networkService.js (3)
123-126
: Enhance readability of authorization header logic.The secret header logic can be more explicit and readable.
Consider this cleaner approach:
- secret !== undefined && (config.headers = { Authorization: `Bearer ${secret}` }); + if (secret) { + config.headers = { Authorization: `Bearer ${secret}` }; + }
164-164
: Strengthen content-type validation.The current content-type check might be fragile for variations in MIME types.
Consider using a more robust check:
- if (contentType && contentType.includes('application/json')) { + if (contentType?.toLowerCase().split(';')[0] === 'application/json') {🧰 Tools
🪛 Biome (1.9.4)
[error] 164-164: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
185-193
: Refactor match logic for better maintainability.The match logic could be more structured using a strategy pattern.
Consider this approach:
- let match; - result = typeof result === "object" ? JSON.stringify(result) : result.toString(); - if (matchMethod === "include") match = result.includes(expectedValue); - else if (matchMethod === "regex") match = new RegExp(expectedValue).test(result); - else match = result === expectedValue; + const matchers = { + include: (result, expected) => result.includes(expected), + regex: (result, expected) => new RegExp(expected).test(result), + equal: (result, expected) => result === expected + }; + + result = typeof result === "object" ? JSON.stringify(result) : result.toString(); + const matcher = matchers[matchMethod] || matchers.equal; + const match = matcher(result, expectedValue);
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Server/service/networkService.js
(3 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
Server/service/networkService.js
[error] 164-164: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (2)
Server/service/networkService.js (2)
1-1
: LGTM! Clean dependency addition and constructor update.The jmespath import and Docker parameter addition look good.
Also applies to: 16-16
169-169
: Enhance error messages and add type validation.The error messages could be more descriptive and include validation for expected types.
Consider these improvements:
- httpResponse.message = "JSONPath Search Error"; + httpResponse.message = `JSONPath Search Error: Invalid path '${jsonPath}'`; - httpResponse.message = "Response Not JSON"; + httpResponse.message = `Expected JSON response but got ${contentType}`; - httpResponse.message = "Empty Result"; + httpResponse.message = `No data found at path '${jsonPath}'`;Also applies to: 174-174, 181-181
✅ Verification successful
🏁 Script executed:
#!/bin/bash # Check for consistent error message patterns across the codebase rg -A 1 'httpResponse\.message = "[^"]+";'Length of output: 478
Action: Enhance error messages with dynamic details and add type validation
The shell script confirms that the error messages in Server/service/networkService.js are hard-coded and generic. These messages at lines 169, 174, and 181 would benefit from incorporating dynamic context—such as capturing the relevant JSON path or content type—and from adding type validation to ensure the response data meets expectations.
- In line 169, replace:
- From:
httpResponse.message = "JSONPath Search Error";
- To:
httpResponse.message = \
JSONPath Search Error: Invalid path '${jsonPath}'`;`- In line 174, replace:
- From:
httpResponse.message = "Response Not JSON";
- To:
httpResponse.message = \
Expected JSON response but got ${contentType}`;`- In line 181, replace:
- From:
httpResponse.message = "Empty Result";
- To:
httpResponse.message = \
No data found at path '${jsonPath}'`;`These changes will provide more descriptive error details, making debugging easier. With the current evidence, please proceed with these improvements.
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.
Hi @YinDongFang ,
Can you please give us some more details about this PR?
What is the feature/problem that is being implemented/solved?
The more details you can add the faster we can review 👍
It's a alternative solution instead of solution in #1634 to implements feature requested in #1573. Supports response validation using JSONPath expressions with three matching strategies. Avoid security problem of executing user code. 🔑 Key Changes
🎬 Example SceneThe expected response data's message field contains "success"// example response data expected
{
message: 'request success!'
} Then we can post monitor as: {
// ...other monitor fields
jsonPath: 'message',
matchMethod: 'include', // default is 'equal'
expectedValue: 'success',
} |
That sounds like a much cleaner / safer solution to me, @ajhollid |
Agreed, I think this is much safer for us. I'll need a little bit of time to play with it but concept looks solid. Thank you @YinDongFang 👍 |
jsonPath: joi.string(), | ||
expectedValue: joi.string(), | ||
matchMethod: joi.string(), |
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.
This is worth doing
jsonPath: joi.string(), | ||
expectedValue: joi.string(), | ||
matchMethod: joi.string(), |
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.
same here, worth addding this to the 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.
Overall looks good to me. I think the nested if/else blocks can be simplified somewhat with early returns, so I think that is worth doing.
There isn't a front end implementation yet, are you planning on doing that?
Server/service/networkService.js
Outdated
else match = result === expectedValue; | ||
|
||
httpResponse.status = match; | ||
httpResponse.message = match ? "Match" : "Not Match"; |
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.
There is an open PR for a localization module that will be added to the application probably sometime today, so after that merge is in please update this PR to use that module for user facing strings.
I think there was one in the first implementation (sandboxed js run) as a PR, but it might have been closed. I remember seeing the screenshots. |
Yes, I will implement the frontend |
Great, we can merge the back end implementation in first once the changes have been made and work on the front end in a new pull request. Thanks for your hard work! |
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.
Actionable comments posted: 1
🧹 Nitpick comments (3)
Server/service/networkService.js (3)
123-126
: Simplify secret header configuration.The current implementation can be made more concise using object shorthand.
Apply this diff:
- secret !== undefined && (config.headers = { Authorization: `Bearer ${secret}` }); + secret && (config.headers = { Authorization: `Bearer ${secret}` });
168-183
: Enhance content-type check robustness.The content-type check could be improved using optional chaining and case-insensitive comparison.
Apply this diff:
- const contentType = response.headers['content-type']; - if (contentType && contentType.includes('application/json')) { + const contentType = response.headers?.['content-type']?.toLowerCase(); + if (contentType?.includes('application/json')) {🧰 Tools
🪛 Biome (1.9.4)
[error] 170-170: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
191-195
: Simplify match logic using a switch statement.The current if-else chain can be made more maintainable using a switch statement.
Apply this diff:
- let match; - result = typeof result === "object" ? JSON.stringify(result) : result.toString(); - if (matchMethod === "include") match = result.includes(expectedValue); - else if (matchMethod === "regex") match = new RegExp(expectedValue).test(result); - else match = result === expectedValue; + result = typeof result === "object" ? JSON.stringify(result) : result.toString(); + const match = { + include: () => result.includes(expectedValue), + regex: () => new RegExp(expectedValue).test(result), + equal: () => result === expectedValue + }[matchMethod]?.() ?? false;
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
Server/service/networkService.js
(3 hunks)
🧰 Additional context used
🪛 Biome (1.9.4)
Server/service/networkService.js
[error] 170-170: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
🔇 Additional comments (2)
Server/service/networkService.js (2)
1-1
: LGTM! Clean dependency injection.The addition of jmespath for JSON path validation and Docker parameter in the constructor follows good dependency injection practices.
Also applies to: 16-16
160-165
: LGTM! Excellent logging implementation.The logging implementation provides detailed context with structured data, making debugging easier.
fd1b153
to
4d12608
Compare
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.
Actionable comments posted: 1
♻️ Duplicate comments (1)
Server/service/networkService.js (1)
198-198
:⚠️ Potential issueRegex Pattern Validation Needs Enhancement
The current implementation directly creates a regular expression from user-supplied input without any restrictions, which could expose the system to ReDoS attacks. Best practices advise validating both the complexity and length of such patterns.
- else if (matchMethod === "regex") match = new RegExp(expectedValue).test(result); + else if (matchMethod === "regex") { + // Validate regex pattern complexity and length + if (expectedValue.length > 1000) { + httpResponse.status = false; + httpResponse.message = "Regex pattern too complex"; + return httpResponse; + } + try { + match = new RegExp(expectedValue).test(result); + } catch (error) { + httpResponse.status = false; + httpResponse.message = "Invalid regex pattern"; + return httpResponse; + } + }
🧹 Nitpick comments (2)
Server/service/networkService.js (2)
18-36
: Add parameter validation in the constructor.Yo! Let's make sure our constructor's got our back by validating those parameters—we don't want undefined dependencies causing trouble later!
constructor(axios, ping, logger, http, Docker, net, stringService) { + if (!axios || !ping || !logger || !http || !Docker || !net || !stringService) { + throw new Error('All dependencies must be provided to NetworkService'); + } this.TYPE_PING = "ping"; // ... rest of the constructor
172-174
: Improve content-type checking with optional chaining.Let's make that content-type check smoother than mom's spaghetti!
- const contentType = response.headers['content-type']; - - if (contentType && contentType.includes('application/json')) { + if (response.headers?.['content-type']?.includes('application/json')) {🧰 Tools
🪛 Biome (1.9.4)
[error] 174-174: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
⛔ Files ignored due to path filters (1)
Server/package-lock.json
is excluded by!**/package-lock.json
📒 Files selected for processing (4)
Server/db/models/Monitor.js
(1 hunks)Server/package.json
(1 hunks)Server/service/networkService.js
(3 hunks)Server/validation/joi.js
(2 hunks)
🚧 Files skipped from review as they are similar to previous changes (3)
- Server/package.json
- Server/validation/joi.js
- Server/db/models/Monitor.js
🧰 Additional context used
🪛 Biome (1.9.4)
Server/service/networkService.js
[error] 174-174: Change to an optional chain.
Unsafe fix: Change to an optional chain.
(lint/complexity/useOptionalChain)
const { url, secret, _id, name, teamId, type, jsonPath, matchMethod, expectedValue } = job.data; | ||
const config = {}; | ||
|
||
job.data.secret !== undefined && | ||
(config.headers = { Authorization: `Bearer ${job.data.secret}` }); | ||
secret !== undefined && (config.headers = { Authorization: `Bearer ${secret}` }); |
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.
🛠️ Refactor suggestion
Enhance secret handling security.
The current secret handling might expose sensitive data in logs. Let's keep that secret sauce under wraps!
- secret !== undefined && (config.headers = { Authorization: `Bearer ${secret}` });
+ if (secret) {
+ // Avoid using template literals with secrets to prevent accidental logging
+ config.headers = { Authorization: 'Bearer ' + secret };
+ }
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const { url, secret, _id, name, teamId, type, jsonPath, matchMethod, expectedValue } = job.data; | |
const config = {}; | |
job.data.secret !== undefined && | |
(config.headers = { Authorization: `Bearer ${job.data.secret}` }); | |
secret !== undefined && (config.headers = { Authorization: `Bearer ${secret}` }); | |
const { url, secret, _id, name, teamId, type, jsonPath, matchMethod, expectedValue } = job.data; | |
const config = {}; | |
if (secret) { | |
// Avoid using template literals with secrets to prevent accidental logging | |
config.headers = { Authorization: 'Bearer ' + secret }; | |
} |
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.
Actionable comments posted: 0
🧹 Nitpick comments (1)
Server/service/networkService.js (1)
153-158
: Refactor to use early returns for cleaner flow.His palms are sweaty looking at these nested if/else blocks! Let's clean it up with early returns.
- if (!expectedValue) { - // not configure expected value, return - httpResponse.status = true; - httpResponse.message = this.http.STATUS_CODES[response.status]; - return httpResponse; - } + if (expectedValue === undefined) { + httpResponse.status = true; + httpResponse.message = this.http.STATUS_CODES[response.status]; + return httpResponse; + }
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
Server/locales/en.json
(1 hunks)Server/service/networkService.js
(3 hunks)Server/service/stringService.js
(1 hunks)
🔇 Additional comments (10)
Server/service/stringService.js (6)
324-326
: LGTM! Yo, this getter's got the right flow!The method follows the established pattern for translation getters, keeping it consistent with the rest of the class.
328-330
: LGTM! This getter's straight outta translation heaven!The method maintains the consistent pattern for translation getters, making it a clean addition to the class.
332-334
: LGTM! This getter's serving up error messages like mom's spaghetti!The method keeps the translation getter pattern consistent, making it a solid addition to the class.
336-338
: LGTM! This getter's dropping empty results like they're hot!The method maintains the translation getter pattern, keeping the class's style consistent.
340-342
: LGTM! This getter's matching success like a rap battle champion!The method follows the established translation getter pattern, maintaining class consistency.
344-346
: LGTM! This getter's handling failures with style!The method maintains the translation getter pattern, keeping it real with the class's consistency.
Server/service/networkService.js (3)
126-129
: Enhance secret handling security.The current secret handling might expose sensitive data in logs. Let's keep that secret sauce under wraps!
- secret !== undefined && (config.headers = { Authorization: `Bearer ${secret}` }); + if (secret) { + // Avoid using template literals with secrets to prevent accidental logging + config.headers = { Authorization: 'Bearer ' + secret }; + }
189-196
: Improve result string conversion for accurate matching.Using
result.toString()
might not yield meaningful results ifresult
is an object. Let's handle that spaghetti code!- result = typeof result === "object" ? JSON.stringify(result) : result.toString(); + result = typeof result === 'object' ? JSON.stringify(result) : result.toString();
197-199
: Regex Pattern Validation Needs Enhancement.The current implementation directly creates a regular expression from user-supplied input without any restrictions, which could expose the system to ReDoS attacks. His knees weak, arms are heavy thinking about those potential DoS attacks!
Run this script to check for potential ReDoS vulnerabilities:
#!/bin/bash # Description: Check for potential ReDoS vulnerabilities in regex patterns # Test: Search for direct RegExp creation from user input rg -A 5 'new RegExp\('Server/locales/en.json (1)
147-153
: LGTM! These translations are dropping bars like Eminem!The translations are clear, concise, and properly formatted. They align perfectly with the HTTP response validation functionality.
@ajhollid I rebased the PR and use the localization service to display message. It looks good. Please review again. |
Thanks @YinDongFang , I will review as soon as possible! |
@YinDongFang May I use your Excalidraw drawing in our documentation for a reference guide when Alex accepts the PR for the next release? |
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.
This looks good to me, thank you for your contribution @YinDongFang ! Much appreciated 👍
result = typeof result === "object" ? JSON.stringify(result) : result.toString(); | ||
if (matchMethod === "include") match = result.includes(expectedValue); | ||
else if (matchMethod === "regex") match = new RegExp(expectedValue).test(result); | ||
else match = result === expectedValue; |
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.
Looks good, this is much easier to read 👍
Sure. You are welcome to use it |
Describe your changes
Support json validation and match method(regex, include, equal) by JSONPath
Test cases:
https://excalidraw.com/#json=2c9IgahseNFk4PNMeDiXL,5wEIYKEyOx0ly_0L4FACEA
Please ensure all items are checked off before requesting a review. "Checked off" means you need to add an "x" character between brackets so they turn into checkmarks.