-
Notifications
You must be signed in to change notification settings - Fork 521
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
fix: Short url fixes #4773
fix: Short url fixes #4773
Conversation
Fixes: #4757, point 2
WalkthroughThe changes primarily involve enhancements to authentication and URL handling across various modules. The Changes
Assessment against linked issues
Possibly related PRs
Suggested labels
Suggested reviewers
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
CodeRabbit Configuration File (
|
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: 10
🧹 Outside diff range and nitpick comments (7)
web/src/router/index.ts (3)
Line range hint
81-89
: Consider adding error handling for invalid URLs.To address the issue of "Short URL not found" errors mentioned in the PR objectives, consider adding error handling logic here. This could involve checking the validity of the
short_url
before storing it and providing appropriate feedback to the user.Here's a suggested implementation:
if (Object.hasOwn(to.query, "short_url")) { const shortUrl = to.query.short_url as string; if (isValidShortUrl(shortUrl)) { window.sessionStorage.setItem("redirectURI", shortUrl); } else { // Handle invalid short URL console.error("Invalid short URL"); // Optionally, redirect to an error page or show a notification } } else { window.sessionStorage.setItem("redirectURI", window.location.href); } // Add this function to validate the short URL function isValidShortUrl(url: string): boolean { // Implement validation logic here // For example, check if it matches a specific pattern or exists in your database return true; // Placeholder return }
81-85
: Add comments to explain short URL handling.To improve code maintainability, consider adding comments to explain the purpose and functionality of the
short_url
handling. This will help future developers understand the logic behind this implementation.Here's a suggested comment:
// Handle short URL redirection // If the query params contain a short_url, store it in session storage // This is used to redirect the user to the correct page after authentication // particularly when accessing shared log search links if (Object.hasOwn(to.query, "short_url")) { window.sessionStorage.setItem("redirectURI", to.query.short_url); }
Line range hint
74-89
: Overall assessment of changesThe changes in this file improve code readability and maintain the existing functionality. However, they don't fully address the specific issues mentioned in the PR objectives, such as problems with incognito mode, SSO, and invalid URL handling.
To fully meet the PR objectives:
- Implement specific handling for incognito mode and SSO scenarios.
- Add error handling for invalid short URLs.
- Address the timezone display issue mentioned in the PR objectives.
Consider adding more comprehensive changes to tackle these issues directly.
src/service/alerts/alert.rs (2)
Line range hint
616-815
: Consider refactoringprocess_dest_template
for improved maintainabilityWhile the function is working as intended, its length and complexity make it a candidate for refactoring. Consider the following suggestions:
- Extract the URL generation logic into separate functions for PromQL and SQL/Custom queries.
- Create a dedicated function for variable replacement to reduce code duplication.
- Use a struct to hold the alert context (start time, end time, etc.) instead of passing multiple parameters.
These changes could improve readability and make the function easier to maintain and test.
Would you like me to provide a sample refactored structure for this function?
Line range hint
1-815
: Consider additional security measuresWhile the code generally handles security well, consider the following improvements:
- In the
send_http_notification
function, ensure that theskip_tls_verify
option is used cautiously and only in controlled environments.- When processing user-provided templates and variables, consider implementing additional sanitization to prevent potential XSS or template injection attacks.
- In the
send_email_notification
function, consider adding rate limiting to prevent potential abuse of the email sending functionality.- Review the error messages returned to ensure they don't leak sensitive information.
Implementing these suggestions could further enhance the security of the alert system.
Would you like me to provide code snippets for implementing any of these security improvements?
src/handler/http/request/short_url/mod.rs (1)
115-116
: Enhance error logging for better debuggingLogging the
redirect
object may not provide meaningful information when a short URL is not found. Consider logging theshort_id
to assist with debugging.Apply this diff:
- log::error!("Short URL not found, {}", &redirect); + log::error!("Short URL not found for short_id: {}", short_id);src/service/short_url.rs (1)
Line range hint
64-91
: Updateretrieve
function to considerorg_id
The
retrieve
function doesn't includeorg_id
when fetching the original URL. This might result in retrieving the wrong URL if the sameshort_id
exists across different organizations.Modify
retrieve
to acceptorg_id
and use it in the retrieval process:-pub async fn retrieve(short_id: &str) -> Option<String> { - db::short_url::get(short_id).await.ok() +pub async fn retrieve(org_id: &str, short_id: &str) -> Option<String> { + let key = format!("{}:{}", org_id, short_id); + db::short_url::get(&key).await.ok() }Adjust calls to
retrieve
throughout the codebase and update the database functions to handle the composite key.
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (9)
- src/common/utils/auth.rs (1 hunks)
- src/common/utils/redirect_response.rs (2 hunks)
- src/handler/http/auth/validator.rs (3 hunks)
- src/handler/http/request/short_url/mod.rs (4 hunks)
- src/handler/http/router/mod.rs (1 hunks)
- src/service/alerts/alert.rs (1 hunks)
- src/service/dashboards/reports.rs (1 hunks)
- src/service/short_url.rs (5 hunks)
- web/src/router/index.ts (1 hunks)
🧰 Additional context used
📓 Path-based instructions (8)
src/common/utils/auth.rs (1)
Pattern
**/*.rs
: You are a smart rustlang pull request reviewer.
You are going to review all the rustlang files.
Be concise, and add a brief explanation to your suggestionsMake sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
src/common/utils/redirect_response.rs (1)
Pattern
**/*.rs
: You are a smart rustlang pull request reviewer.
You are going to review all the rustlang files.
Be concise, and add a brief explanation to your suggestionsMake sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
src/handler/http/auth/validator.rs (1)
Pattern
**/*.rs
: You are a smart rustlang pull request reviewer.
You are going to review all the rustlang files.
Be concise, and add a brief explanation to your suggestionsMake sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
src/handler/http/request/short_url/mod.rs (1)
Pattern
**/*.rs
: You are a smart rustlang pull request reviewer.
You are going to review all the rustlang files.
Be concise, and add a brief explanation to your suggestionsMake sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
src/handler/http/router/mod.rs (1)
Pattern
**/*.rs
: You are a smart rustlang pull request reviewer.
You are going to review all the rustlang files.
Be concise, and add a brief explanation to your suggestionsMake sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
src/service/alerts/alert.rs (1)
Pattern
**/*.rs
: You are a smart rustlang pull request reviewer.
You are going to review all the rustlang files.
Be concise, and add a brief explanation to your suggestionsMake sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
src/service/dashboards/reports.rs (1)
Pattern
**/*.rs
: You are a smart rustlang pull request reviewer.
You are going to review all the rustlang files.
Be concise, and add a brief explanation to your suggestionsMake sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
src/service/short_url.rs (1)
Pattern
**/*.rs
: You are a smart rustlang pull request reviewer.
You are going to review all the rustlang files.
Be concise, and add a brief explanation to your suggestionsMake sure the responses are not too verbose and keep the suggestions to the point i.e. actionable.
🔇 Additional comments (18)
web/src/router/index.ts (2)
74-78
: Improved readability of path checking conditions.The expansion of the path checking conditions into a multi-line format enhances code readability and maintainability. This change is a positive step towards cleaner code.
Line range hint
74-89
: Clarification needed on addressing PR objectives.While the changes improve the code structure, it's not immediately clear how they address the specific issues mentioned in the PR objectives, such as:
- Redirection problems in incognito mode with SSO.
- Handling of "Short URL not found" errors.
- Timezone display issues in SSO and incognito mode.
Could you please clarify how these changes relate to resolving these specific problems?
src/service/dashboards/reports.rs (1)
621-621
: LGTM! Verify short URL functionality across the application.The addition of
org_id
to theshort_url::shorten
function call aligns with the PR objectives and should help resolve the issues with sharing log search links. This change appears to be correct and consistent.To ensure this change doesn't introduce any regressions, please run the following verification script:
✅ Verification successful
Verified: All
short_url::shorten
calls includeorg_id
as the first argument.No issues found.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Verify that all calls to short_url::shorten now include org_id as the first argument. # Test: Search for all occurrences of short_url::shorten. Expect: All calls should include org_id as the first argument. rg --type rust 'short_url::shorten\s*\(' -A 2Length of output: 782
src/service/alerts/alert.rs (3)
Line range hint
1-815
: Overall assessment: Good implementation with room for improvementsThe alert system implementation is generally well-structured and functional. The recent change to include
org_id
in short URL generation is a positive improvement. However, there are opportunities for enhancing the code:
- Refactor large functions like
process_dest_template
andsave
for better maintainability.- Address the commented-out alert evaluation code in the
save
function.- Implement additional security measures as suggested.
- Consider adding more comprehensive error handling and logging throughout the file.
These improvements would make the code more robust, maintainable, and secure.
Line range hint
807-815
: LGTM: Short URL generation for alert URLsThe change to include the
org_id
in theshort_url::shorten
function call is a good improvement. This ensures that short URLs are organization-specific, which is important for multi-tenant systems.To ensure this change is consistent across the codebase, let's verify other usages of
short_url::shorten
:✅ Verification successful
Consistency of
short_url::shorten
Usage ConfirmedAll instances of
short_url::shorten
across the codebase now include theorg_id
parameter, ensuring consistent and organization-specific URL shortening.🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash # Description: Check for other usages of short_url::shorten to ensure consistency rg --type rust "short_url::shorten\(" -C 3Length of output: 98
Script:
#!/bin/bash # Description: Verify all usages of short_url::shorten to ensure consistency rg --type rust 'short_url::shorten\s*\(' -C 3Length of output: 1558
Line range hint
78-196
: Address commented-out alert evaluation codeThere's a commented-out section for alert evaluation in the
save
function. This raises a few concerns:
- If this code is no longer needed, it should be removed to avoid confusion.
- If it's still relevant but causing issues (as the comment suggests), consider refactoring it to handle large data volumes more efficiently.
- If it's a temporary measure, add a TODO comment explaining why it's commented out and when it should be re-enabled.
Additionally, consider breaking down this large function into smaller, more focused functions to improve readability and maintainability.
Let's check if there are any related TODO comments or issues:
src/service/short_url.rs (1)
Line range hint
112-135
: Adjust tests to reflect changes inorg_id
handlingEnsure that test cases account for the updated storage and retrieval mechanisms involving
org_id
. This will verify that the functions work correctly with the new logic.Update the test functions to use the modified
retrieve
function and check for organization-specific behavior.src/common/utils/redirect_response.rs (1)
74-101
: Good use of builder pattern for constructing redirect responsesThe introduction of
RedirectResponseBuilder
enhances flexibility and readability in constructingRedirectResponse
instances.src/common/utils/auth.rs (1)
409-409
:⚠️ Potential issuePotential Security Risk: Bypassing Permission Checks for
/short
PathsAdding
|| path.contains("/short")
to the condition means that any request with/short
in its path will bypass permission checks (bypass_check: true
). This could unintentionally allow unauthorized access to protected resources if other endpoints contain/short
in their paths. Please verify that this change does not introduce security vulnerabilities and consider making the condition more specific to the intended endpoint.Run the following script to identify all routes containing
/short
to assess potential security implications:src/handler/http/auth/validator.rs (9)
36-36
: ImportingRedirectResponseBuilder
is appropriateThe addition of
redirect_response::RedirectResponseBuilder
is necessary for handling redirect responses in authentication failures, enhancing the redirect functionality.
647-647
: Updatingoo_validator
function signature improves error handlingChanging the
oo_validator
function to acceptResult<AuthExtractor, Error>
allows for better handling of authentication extraction errors directly within the function.
650-652
: Extracting relative path and identifying short URLsThe introduction of
extract_relative_path
andis_short_url_path
functions helps in accurately determining if a request is for a short URL, which is crucial for conditional error handling.
654-663
: Handling authentication extraction errors for short URLsThe modified error handling appropriately differentiates between short URLs and other paths. If authentication extraction fails for a short URL, the user is redirected, improving the user experience.
665-671
: Conditional error handling after internal validationBy checking
is_short_url
afteroo_validator_internal
, the code ensures that authentication failures for short URLs result in a redirect response, while other paths receive standard error handling.
802-810
: New helper functionextract_relative_path
enhances path handlingThe
extract_relative_path
function efficiently removes the base URI and path prefix, simplifying the extraction of the relative path for further processing.
812-817
: New helper functionis_short_url_path
accurately detects short URL pathsThe
is_short_url_path
function correctly identifies short URL requests by checking the second segment of the path, which is essential for custom authentication handling.
825-836
: Redirecting on authentication failure for short URLsThe
handle_auth_failure_for_redirect
function constructs a redirect response when authentication fails on short URLs. Including the original URL as a query parameter facilitates user redirection post-authentication.
838-850
: Functionextract_full_url
correctly constructs the complete request URLThe
extract_full_url
function accurately assembles the full URL, including the scheme, host, path, and query parameters, which is essential for redirecting users back to their intended destination after authentication.
pub async fn shorten(org_id: web::Path<String>, body: web::Bytes) -> Result<HttpResponse, Error> { | ||
let req: config::meta::short_url::ShortenUrlRequest = match serde_json::from_slice(&body) { | ||
Ok(v) => v, | ||
Err(e) => return Ok(MetaHttpResponse::bad_request(e)), |
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.
Avoid exposing internal error details in responses
Returning the raw deserialization error e
to the client may leak internal implementation details. Consider returning a generic error message to prevent potential information disclosure.
Apply this diff to fix:
- Err(e) => return Ok(MetaHttpResponse::bad_request(e)),
+ Err(_) => return Ok(MetaHttpResponse::bad_request("Invalid request body")),
📝 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.
Err(e) => return Ok(MetaHttpResponse::bad_request(e)), | |
Err(_) => return Ok(MetaHttpResponse::bad_request("Invalid request body")), |
Ok( | ||
HttpResponse::InternalServerError().json(meta::http::HttpResponse::error( | ||
StatusCode::INTERNAL_SERVER_ERROR.into(), | ||
e.to_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.
Avoid including internal error messages in HTTP responses
Exposing internal error messages (e.to_string()
) in the HTTP response body may reveal sensitive information. It's better to return a generic error message to the client.
Apply this diff to fix:
- Ok(
- HttpResponse::InternalServerError().json(meta::http::HttpResponse::error(
- StatusCode::INTERNAL_SERVER_ERROR.into(),
- e.to_string(),
- )),
- )
+ Ok(
+ HttpResponse::InternalServerError().json(meta::http::HttpResponse::error(
+ StatusCode::INTERNAL_SERVER_ERROR.into(),
+ "Internal server error".to_string(),
+ )),
+ )
📝 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.
Ok( | |
HttpResponse::InternalServerError().json(meta::http::HttpResponse::error( | |
StatusCode::INTERNAL_SERVER_ERROR.into(), | |
e.to_string(), | |
)), | |
) | |
Ok( | |
HttpResponse::InternalServerError().json(meta::http::HttpResponse::error( | |
StatusCode::INTERNAL_SERVER_ERROR.into(), | |
"Internal server error".to_string(), | |
)), | |
) |
) -> Result<HttpResponse, Error> { | ||
log::info!( | ||
"short_url::retrieve handler called for path: {}", | ||
req.path() | ||
); | ||
let short_id = short_id.into_inner(); | ||
let (_org_id, short_id) = path.into_inner(); |
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.
Use org_id
to enforce authorization and data isolation
The org_id
parameter is extracted but not used, which can lead to security issues by potentially allowing access to short URLs across organizations. Ensure that org_id
is used to retrieve the short URL, enforcing proper authorization.
Apply this diff to fix:
- let (_org_id, short_id) = path.into_inner();
- let original_url = short_url::retrieve(&short_id).await;
+ let (org_id, short_id) = path.into_inner();
+ let original_url = short_url::retrieve(&org_id, &short_id).await;
And update the retrieve
function in the short_url
service to accept org_id
and enforce authorization accordingly.
Committable suggestion was skipped due to low confidence.
fn construct_short_url(org_id: &str, short_id: &str) -> String { | ||
format!( | ||
"{}/{}/{}{}{}", | ||
get_base_url(), | ||
"api", | ||
org_id, | ||
SHORT_URL_WEB_PATH, | ||
short_id | ||
)) | ||
) | ||
} |
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.
Ensure correct URL formatting in construct_short_url
The format string in construct_short_url
may result in an incorrect URL due to missing slashes between components. Specifically, there might be a missing slash between "api"
and org_id
, which could lead to malformed URLs.
Consider updating the format string to properly include slashes between all parts of the URL. For example:
fn construct_short_url(org_id: &str, short_id: &str) -> String {
format!(
- "{}/{}/{}{}{}",
+ "{}/{}/{}/{}{}",
get_base_url(),
"api",
org_id,
SHORT_URL_WEB_PATH,
short_id
)
}
📝 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.
fn construct_short_url(org_id: &str, short_id: &str) -> String { | |
format!( | |
"{}/{}/{}{}{}", | |
get_base_url(), | |
"api", | |
org_id, | |
SHORT_URL_WEB_PATH, | |
short_id | |
)) | |
) | |
} | |
fn construct_short_url(org_id: &str, short_id: &str) -> String { | |
format!( | |
"{}/{}/{}/{}{}", | |
get_base_url(), | |
"api", | |
org_id, | |
SHORT_URL_WEB_PATH, | |
short_id | |
) | |
} |
fn get_short_id_from_url(org_id: &str, short_url: &str) -> Option<String> { | ||
let prefix = format!("{}api/{}{}", get_base_url(), org_id, SHORT_URL_WEB_PATH); | ||
short_url.strip_prefix(&prefix).map(|s| s.to_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.
Correct the URL prefix in get_short_id_from_url
The format string for prefix
in get_short_id_from_url
may be missing a slash between "api"
and org_id
, potentially causing incorrect extraction of short_id
.
Revise the format string to include the missing slash:
fn get_short_id_from_url(org_id: &str, short_url: &str) -> Option<String> {
- let prefix = format!("{}api/{}{}", get_base_url(), org_id, SHORT_URL_WEB_PATH);
+ let prefix = format!("{}api/{}/{}{}", get_base_url(), org_id, SHORT_URL_WEB_PATH);
short_url.strip_prefix(&prefix).map(|s| s.to_string())
}
📝 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.
fn get_short_id_from_url(org_id: &str, short_url: &str) -> Option<String> { | |
let prefix = format!("{}api/{}{}", get_base_url(), org_id, SHORT_URL_WEB_PATH); | |
short_url.strip_prefix(&prefix).map(|s| s.to_string()) | |
} | |
fn get_short_id_from_url(org_id: &str, short_url: &str) -> Option<String> { | |
let prefix = format!("{}api/{}/{}{}", get_base_url(), org_id, SHORT_URL_WEB_PATH); | |
short_url.strip_prefix(&prefix).map(|s| s.to_string()) | |
} |
async fn store_short_url( | ||
org_id: &str, | ||
short_id: &str, | ||
original_url: &str, | ||
) -> Result<String, anyhow::Error> { | ||
let entry = ShortUrlRecord::new(short_id, original_url); | ||
db::short_url::set(short_id, entry).await?; | ||
Ok(construct_short_url(org_id, short_id)) |
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.
Associate org_id
with stored short URLs in the database
The store_short_url
function accepts org_id
, but it doesn't use it when storing the short URL. This could lead to conflicts if different organizations generate the same short_id
, as the short_id
is used as the key without considering org_id
.
Modify the storage function to include org_id
when storing the short URL to ensure uniqueness per organization. For example:
fn store_short_url(
org_id: &str,
short_id: &str,
original_url: &str,
) -> Result<String, anyhow::Error> {
let entry = ShortUrlRecord::new(short_id, original_url);
- db::short_url::set(short_id, entry).await?;
+ let key = format!("{}:{}", org_id, short_id);
+ db::short_url::set(&key, entry).await?;
Ok(construct_short_url(org_id, short_id))
}
Ensure that the retrieval function and database schema are updated accordingly.
📝 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.
async fn store_short_url( | |
org_id: &str, | |
short_id: &str, | |
original_url: &str, | |
) -> Result<String, anyhow::Error> { | |
let entry = ShortUrlRecord::new(short_id, original_url); | |
db::short_url::set(short_id, entry).await?; | |
Ok(construct_short_url(org_id, short_id)) | |
async fn store_short_url( | |
org_id: &str, | |
short_id: &str, | |
original_url: &str, | |
) -> Result<String, anyhow::Error> { | |
let entry = ShortUrlRecord::new(short_id, original_url); | |
let key = format!("{}:{}", org_id, short_id); | |
db::short_url::set(&key, entry).await?; | |
Ok(construct_short_url(org_id, short_id)) |
let query_string: String = self | ||
.query_params | ||
.iter() | ||
.map(|(key, value)| format!("{}={}", key, value)) | ||
.collect::<Vec<String>>() | ||
.join("&"); | ||
|
||
redirect_uri = format!("{}?{}", redirect_uri, query_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.
Ensure query parameters are URL-encoded
When constructing the query string, keys and values should be URL-encoded to handle special characters correctly. Currently, keys and values are not encoded, which can lead to malformed URLs if they contain characters that need to be percent-encoded.
Apply this diff to URL-encode the query parameters:
+use url::form_urlencoded::Serializer;
...
- let query_string: String = self
- .query_params
- .iter()
- .map(|(key, value)| format!("{}={}", key, value))
- .collect::<Vec<String>>()
- .join("&");
+ let mut serializer = url::form_urlencoded::Serializer::new(String::new());
+ for (key, value) in &self.query_params {
+ serializer.append_pair(key, value);
+ }
+ let query_string = serializer.finish();
You may need to add the url
crate to your dependencies in Cargo.toml
if it's not already included.
📝 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.
let query_string: String = self | |
.query_params | |
.iter() | |
.map(|(key, value)| format!("{}={}", key, value)) | |
.collect::<Vec<String>>() | |
.join("&"); | |
redirect_uri = format!("{}?{}", redirect_uri, query_string); | |
use url::form_urlencoded::Serializer; | |
let mut serializer = url::form_urlencoded::Serializer::new(String::new()); | |
for (key, value) in &self.query_params { | |
serializer.append_pair(key, value); | |
} | |
let query_string = serializer.finish(); | |
redirect_uri = format!("{}?{}", redirect_uri, query_string); |
let expected_uri = | ||
"/web?redirect_url=http://localhost:5080/api/default/short/1234&user_id=42"; | ||
assert_eq!(redirect_response.build_full_redirect_uri(), expected_uri); | ||
|
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.
Account for unordered query parameters in tests
Since HashMap
does not guarantee the order of its entries, the actual query parameters in the URI might not be in the same order as specified. This can cause tests to fail intermittently. Consider parsing the query parameters and asserting their presence regardless of order.
You can adjust the test as follows:
- assert_eq!(redirect_response.build_full_redirect_uri(), expected_uri);
+ let actual_uri = redirect_response.build_full_redirect_uri();
+ let uri_parts: Vec<&str> = actual_uri.split('?').collect();
+ assert_eq!(uri_parts[0], "/web");
+ let query_params: Vec<&str> = uri_parts[1].split('&').collect();
+ assert!(query_params.contains(&"redirect_url=http://localhost:5080/api/default/short/1234"));
+ assert!(query_params.contains(&"user_id=42"));
📝 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.
let expected_uri = | |
"/web?redirect_url=http://localhost:5080/api/default/short/1234&user_id=42"; | |
assert_eq!(redirect_response.build_full_redirect_uri(), expected_uri); | |
let expected_uri = | |
"/web?redirect_url=http://localhost:5080/api/default/short/1234&user_id=42"; | |
let actual_uri = redirect_response.build_full_redirect_uri(); | |
let uri_parts: Vec<&str> = actual_uri.split('?').collect(); | |
assert_eq!(uri_parts[0], "/web"); | |
let query_params: Vec<&str> = uri_parts[1].split('&').collect(); | |
assert!(query_params.contains(&"redirect_url=http://localhost:5080/api/default/short/1234")); | |
assert!(query_params.contains(&"user_id=42")); |
let mut redirect_uri = self.redirect_relative_uri.clone(); | ||
|
||
// If there are query parameters, append them to the URI. | ||
if !self.query_params.is_empty() { | ||
let query_string: String = self | ||
.query_params | ||
.iter() | ||
.map(|(key, value)| format!("{}={}", key, value)) | ||
.collect::<Vec<String>>() | ||
.join("&"); | ||
|
||
redirect_uri = format!("{}?{}", redirect_uri, query_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.
Handle existing query parameters in redirect URI
If redirect_relative_uri
already contains query parameters, appending another ?
would result in an invalid URL. Consider checking if redirect_relative_uri
contains a ?
and use the appropriate separator (?
or &
) when appending the query parameters.
Apply this diff to fix the issue:
if !self.query_params.is_empty() {
+ let separator = if redirect_uri.contains('?') { '&' } else { '?' };
- redirect_uri = format!("{}?{}", redirect_uri, query_string);
+ redirect_uri = format!("{}{}{}", redirect_uri, separator, query_string);
}
📝 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.
let mut redirect_uri = self.redirect_relative_uri.clone(); | |
// If there are query parameters, append them to the URI. | |
if !self.query_params.is_empty() { | |
let query_string: String = self | |
.query_params | |
.iter() | |
.map(|(key, value)| format!("{}={}", key, value)) | |
.collect::<Vec<String>>() | |
.join("&"); | |
redirect_uri = format!("{}?{}", redirect_uri, query_string); | |
let mut redirect_uri = self.redirect_relative_uri.clone(); | |
// If there are query parameters, append them to the URI. | |
if !self.query_params.is_empty() { | |
let query_string: String = self | |
.query_params | |
.iter() | |
.map(|(key, value)| format!("{}={}", key, value)) | |
.collect::<Vec<String>>() | |
.join("&"); | |
let separator = if redirect_uri.contains('?') { '&' } else { '?' }; | |
redirect_uri = format!("{}{}{}", redirect_uri, separator, query_string); | |
} |
.service(short_url::shorten) | ||
.service(short_url::retrieve), |
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.
Reconsider moving short_url::retrieve
behind authentication middleware
By adding short_url::retrieve
to get_service_routes
, which applies authentication middleware, unauthenticated users may not be able to access short URLs. Since one of the PR objectives is to fix issues where users cannot access shared short URLs, especially in incognito mode or when using SSO, moving this route behind authentication might prevent users from retrieving short URLs without logging in. Consider making short_url::retrieve
accessible without requiring authentication to ensure that shared links work as intended.
To address this, you can move short_url::retrieve
to an unauthenticated route. Here's a suggested change:
- .service(short_url::shorten)
- .service(short_url::retrieve),
+ .service(short_url::shorten),
In the get_basic_routes
function, add short_url::retrieve
without authentication:
cfg.service(
web::scope("/auth")
.wrap(cors.clone())
.service(users::authentication)
.service(users::get_presigned_url)
.service(users::get_auth),
);
+
+cfg.service(
+ web::scope("/short")
+ .wrap(cors.clone())
+ .service(short_url::retrieve),
+);
Committable suggestion was skipped due to low confidence.
Fixes #4757
Summary by CodeRabbit
Release Notes
New Features
Bug Fixes
Documentation
Tests