-
Notifications
You must be signed in to change notification settings - Fork 30
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
[breaking] Technical debt #306
base: main
Are you sure you want to change the base?
Conversation
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThis pull request introduces a series of modifications across multiple files in the Changes
Possibly related PRs
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 (
|
@coderabbitai review |
✅ Actions performedReview triggered.
|
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
🧹 Outside diff range and nitpick comments (6)
src/controller/inn.rs (1)
Line range hint
980-985
: Simplify Conditional Logic for Better ReadabilityYou can simplify the conditional statements in the
inn
function by combining conditions to reduce redundancy and enhance clarity.Apply this diff to simplify the code:
- if inn.is_private() { - if joined_inns.contains(&iid) || is_site_admin { - index = get_pids_by_iids(&DB, &[iid], &page_params)?; - } - } else { - index = get_pids_by_iids(&DB, &[iid], &page_params)?; - } + if !inn.is_private() || joined_inns.contains(&iid) || is_site_admin { + index = get_pids_by_iids(&DB, &[iid], &page_params)?; + }README.md (1)
56-56
: Consider adding a note about private documentationIt would be helpful to add a note explaining why private items are being documented and who the target audience is for this documentation.
Consider adding this note:
```bash cargo doc --no-deps --document-private-items --open
+Note: This command generates documentation for both public and private items,
+intended for maintainers and contributors to understand internal implementation details.</blockquote></details> <details> <summary>src/controller/meta_handler.rs (2)</summary><blockquote> `74-77`: **Improved data access pattern, but consider enhancing error handling** The new approach using `get_one` and the `User` struct is more maintainable and type-safe. However, consider adding specific error handling for the database query. Consider this enhancement: ```diff - let user: User = get_one(&DB, "users", claim.uid)?; + let user: User = get_one(&DB, "users", claim.uid) + .map_err(|e| { + error!("Failed to fetch user {}: {}", claim.uid, e); + AppError::NotFound + })?;
Line range hint
93-93
: Consider implementing CSS minificationThe TODO comment indicates missing CSS minification. This could improve performance by reducing the payload size.
Would you like me to help implement CSS minification using a Rust-based solution? I can suggest using the
lightningcss
crate or provide a build-time minification script.src/controller/mod.rs (1)
299-303
: Add documentation and consider pattern matching foris_private
.The new method is functionally correct but could be improved for clarity and maintainability.
Consider this alternative implementation:
- fn is_private(&self) -> bool { - InnType::from(self.inn_type) == InnType::Private - || InnType::from(self.inn_type) == InnType::PrivateHidden - } + /// Returns true if the inn has private access restrictions + /// (either Private or PrivateHidden type) + fn is_private(&self) -> bool { + match InnType::from(self.inn_type) { + InnType::Private | InnType::PrivateHidden => true, + _ => false, + } + }src/controller/user.rs (1)
767-772
: Consider refactoring language validationThe hardcoded language validation could be improved by:
- Moving supported languages to a constant or configuration
- Using a proper language code enum or validation system
This would make it easier to maintain and extend supported languages.
+ const SUPPORTED_LANGUAGES: &[&str] = &["en", "zh_cn", "ja", "fr"]; + match input.lang.as_str() { - "en" | "zh_cn" | "ja" | "fr" => { + lang if SUPPORTED_LANGUAGES.contains(&lang) => { claim.update_lang(&DB, &input.lang)?; user.lang = Some(input.lang.clone()); } _ => {} };
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
📒 Files selected for processing (7)
README.md
(1 hunks)src/controller/admin.rs
(1 hunks)src/controller/inn.rs
(1 hunks)src/controller/message.rs
(4 hunks)src/controller/meta_handler.rs
(2 hunks)src/controller/mod.rs
(6 hunks)src/controller/user.rs
(4 hunks)
🔇 Additional comments (10)
README.md (1)
56-56
: Verify the intention behind documenting private items
The addition of --document-private-items
flag will expose documentation for private implementation details. While this can be helpful for maintainers, it might not align with the project's encapsulation strategy.
Let's check if this change is consistent with the project's documentation approach:
✅ Verification successful
Based on the codebase analysis, I can now generate the final response:
Documentation change aligns with project's practices
The addition of --document-private-items
flag is consistent with the project's documentation approach, as evidenced by:
- The extensive use of private documentation comments (
///
) throughout the codebase, particularly insrc/controller/
modules - The presence of detailed internal API documentation for private functions and implementation details
- The project's focus on developer understanding, shown by comprehensive documentation of internal workings
The change helps make this internal documentation accessible through cargo doc
, benefiting maintainers and contributors.
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check current documentation practices
# Look for any documentation guidelines or discussions about private items
# Check if there are any existing documentation guidelines
fd -g "*CONTRIBUTING*" -g "*DEVELOPMENT*" -g "*DOCS*" -X cat {} 2>/dev/null
# Check for any discussions about documentation in recent commits
git log --grep="doc" --grep="documentation" -i --pretty=format:"%h %s" -n 5
Length of output: 67
Script:
#!/bin/bash
# Let's check the README.md content to understand the documentation context
cat README.md
# Also check for any Rust documentation comments in the codebase
rg "///" -A 2
# Look for any configuration files that might have documentation settings
fd -g "*.toml" -X cat {}
Length of output: 57350
src/controller/message.rs (3)
10-10
: LGTM: Import changes align with the new data access pattern.
The addition of set_one
import supports the transition to direct user object manipulation, which is a cleaner approach.
38-49
:
Fix incorrect username in template data
There's a bug in the template data construction. The receiver_name
is being set to the sender's username (user.username
) instead of the recipient's username (rcpt.username
).
Apply this fix:
let page_message = PageMessage {
receiver_id: uid,
page_data: PageData::new(&title, &site_config, Some(claim), false),
pub_key: rcpt.pub_key,
- receiver_name: user.username,
+ receiver_name: rcpt.username,
};
Likely invalid or redundant comment.
133-133
:
Remove HTML cleaning for public key
Using clean_html
on a public key is incorrect as it could alter the key's content. Public keys should be handled as raw data without any sanitization.
Apply this fix:
- let pub_key = clean_html(&input.pub_key);
+ let pub_key = input.pub_key;
Likely invalid or redundant comment.
src/controller/meta_handler.rs (1)
3-4
: LGTM! Import changes align with the new data access pattern
The addition of User
and get_one
imports, coupled with the removal of u32_to_ivec
, indicates a positive shift towards using higher-level database abstractions.
src/controller/admin.rs (1)
Line range hint 263-267
: Potential XSS vulnerability in feed error message display
The current implementation displays feed error messages without proper HTML sanitization, which could lead to XSS vulnerabilities if the error messages contain malicious HTML/JavaScript content. This is particularly critical since the admin template has HTML escaping disabled (escape = "none"
).
Consider applying these improvements:
"feed_errs" => {
let id = ivec_to_u32(&k);
let msg = String::from_utf8_lossy(&v);
- ones.push(format!("{id}: {msg}"));
+ let sanitized_msg = clean_html(&msg);
+ ones.push(format!("{id}: {sanitized_msg}"));
}
Additional recommendations:
- Consider adding timestamp information for better error tracking
- Implement pagination or limit the number of errors shown to prevent potential DoS
Let's verify the potential impact:
src/controller/mod.rs (1)
12-14
: Documentation needs clarification for empty value fields.
Several table definitions now show empty value fields in the documentation. This change could impact data migration and backwards compatibility. Please:
- Clarify if these fields still store values
- Document the expected value format if applicable
- Update migration guides if necessary
Affected tables: user_following, user_followers, user_stats, messages, and others.
Consider maintaining a separate schema version documentation to track these changes and help with future migrations.
Also applies to: 17-19, 33-34, 36-36, 54-57, 59-59, 61-61, 68-68, 70-72, 76-76, 83-85, 99-99, 106-107
✅ Verification successful
Let me check the README.md content and search for any database schema related information before making a conclusion.
Let me check the actual database initialization and usage patterns to understand if these empty values are intentional.
Let me check the actual database value insertion patterns for these specific tables.
Based on the evidence gathered, I can now generate the final response:
Documentation accurately reflects empty value fields - they are used as key-only indices
The empty value fields in the documentation are correct and intentional. The code shows that these tables are used as key-only indices where:
user_following
anduser_followers
tables store relationships using composite keys (uid#uid
) with empty values (&[]
)user_stats
stores counts with timestamp-based keys and numeric values
The implementation consistently uses these tables as documented:
- Following/follower relationships are tracked by key existence only
- Stats are tracked with incrementing counters
- No default values are needed as the presence/absence of keys is sufficient
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Description: Check for any migration scripts or documentation
# that might need updating due to schema changes
# Look for migration files
fd -t f "migration|upgrade" -X echo "Found migration file: {}"
# Check for documentation about database schema
fd -t f "README|SCHEMA|DATABASE" -X echo "Found documentation: {}"
Length of output: 166
Script:
#!/bin/bash
# Check README.md content for database schema information
cat README.md
# Search for any database schema related files or documentation in the codebase
rg -i "schema|database structure|table structure" --type rust
# Look for any database initialization or setup code
ast-grep --pattern 'fn $_($$$ db: $$$) {
$$$
}'
Length of output: 3559
Script:
#!/bin/bash
# Look for database tree initialization and usage
rg -A 5 "open_tree|Tree::new" --type rust
# Check for any database value insertion patterns
ast-grep --pattern 'insert($$$)'
# Look for database related tests that might show expected values
fd -t f "test" -e rs -X rg -l "user_following|user_followers|user_stats"
Length of output: 56121
Script:
#!/bin/bash
# Search for user_following/followers/stats insertions and their values
rg -B 2 -A 2 "user_following|user_followers|user_stats" --type rust | grep -A 2 "insert"
# Look for any tests or documentation that shows the expected format
ast-grep --pattern 'fn test_$_($$$) {
$$$
user_following$$$
$$$
}'
# Check for any comments or documentation about these tables
rg -i "user_following|user_followers|user_stats" --type rust --type md -C 2
Length of output: 7448
src/controller/user.rs (3)
644-644
: LGTM: PageUserSetting struct update
The addition of the home_page
field to PageUserSetting is consistent with the refactoring to store user preferences in the User struct.
765-765
: LGTM: Home page preference update
The assignment of the home_page preference is properly implemented.
1217-1217
: LGTM: Session claim language preference
The addition of the language preference to the session claim is properly implemented and consistent with the refactoring goals.
let mut user: User = get_one(&DB, "users", claim.uid)?; | ||
user.pub_key = Some(pub_key); | ||
set_one(&DB, "users", claim.uid, &user)?; |
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
Add size limit validation for public key
The code should validate the size of the public key to prevent potential DoS attacks through extremely large keys or database storage issues.
Consider adding a size limit check:
let mut user: User = get_one(&DB, "users", claim.uid)?;
+ if input.pub_key.len() > 2048 { // Adjust size limit as needed
+ return Err(AppError::InvalidInput("Public key too large".into()));
+ }
user.pub_key = Some(pub_key);
set_one(&DB, "users", claim.uid, &user)?;
Committable suggestion skipped: line range outside the PR's diff.
let user: User = get_one(&DB, "users", claim.uid)?; | ||
let pub_key = user.pub_key.unwrap_or_default(); |
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.
💡 Codebase verification
Public key validation is handled through HTML sanitization only
Based on the code analysis, the public key is only sanitized using clean_html()
before storage, without any cryptographic validation. While this prevents XSS attacks, it doesn't ensure the key meets cryptographic standards.
- The key is stored in
User.pub_key
as an optional String - In
key_post()
, the key is only processed throughclean_html(&input.pub_key)
- No cryptographic validation is performed despite the codebase having crypto capabilities (as seen in
src/lib.rs
andsrc/controller/user.rs
)
🔗 Analysis chain
Verify public key format validation
While the code handles the absence of a public key gracefully, there's no validation of the public key format. Consider adding validation to ensure the key meets the required format and security standards.
Let's check if there's any key validation elsewhere in the codebase:
🏁 Scripts executed
The following scripts were executed for the analysis:
Script:
#!/bin/bash
# Search for public key validation patterns
rg -A 5 'pub_key.*valid|validate.*pub_key|check.*pub_key'
# Search for any crypto-related validation functions
ast-grep --pattern 'fn $_(pub_key: $_) {
$$$
}'
Length of output: 111
Script:
#!/bin/bash
# Let's search for public key related code more broadly
rg -A 5 "pub_key"
# Also search for any key validation or verification functions
rg -A 5 "verify.*key|validate.*key|check.*key"
# Look for crypto-related imports that might handle key validation
rg "use.*crypto"
Length of output: 134574
Script:
#!/bin/bash
# Let's search for key-related functionality and validation
rg -A 5 "pub_key|public.*key" src/
# Look for any crypto-related code or key handling
rg -A 5 "crypto|key.*valid|verify" src/
# Check for any key-related functions in message handling
ast-grep --pattern 'fn $_(pub_key: $_) {
$$$
}' src/controller/message.rs
Length of output: 3835
lang: Option<String>, | ||
home_page: u8, | ||
pub_key: Option<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.
🛠️ Refactor suggestion
Document and validate new User fields.
The new fields need documentation and validation:
lang
: Consider validating against supported languages inI18N
home_page
: Document valid values and add validation
Add validation and documentation:
#[derive(Default, Encode, Decode, Serialize, Debug)]
struct User {
uid: u32,
username: String,
password_hash: String,
recovery_hash: Option<String>,
created_at: i64,
role: u8,
url: String,
about: String,
+ /// User's preferred language code (e.g., "en", "zh_cn")
+ #[garde(custom(supported_language))]
lang: Option<String>,
+ /// User's preferred home page view
+ /// Values:
+ /// - 0: Default view
+ /// - 1: Timeline view
+ /// - 2: Custom view
+ #[garde(range(max = 2))]
home_page: u8,
pub_key: Option<String>,
}
+impl User {
+ fn supported_language(lang: &Option<String>) -> garde::Result {
+ if let Some(lang) = lang {
+ if !["en", "zh_cn", "ja", "fr"].contains(&lang.as_str()) {
+ return Err(garde::Error::new("unsupported language"));
+ }
+ }
+ Ok(())
+ }
+}
📝 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.
lang: Option<String>, | |
home_page: u8, | |
pub_key: Option<String>, | |
#[derive(Default, Encode, Decode, Serialize, Debug)] | |
struct User { | |
uid: u32, | |
username: String, | |
password_hash: String, | |
recovery_hash: Option<String>, | |
created_at: i64, | |
role: u8, | |
url: String, | |
about: String, | |
/// User's preferred language code (e.g., "en", "zh_cn") | |
#[garde(custom(supported_language))] | |
lang: Option<String>, | |
/// User's preferred home page view | |
/// Values: | |
/// - 0: Default view | |
/// - 1: Timeline view | |
/// - 2: Custom view | |
#[garde(range(max = 2))] | |
home_page: u8, | |
pub_key: Option<String>, | |
} | |
impl User { | |
fn supported_language(lang: &Option<String>) -> garde::Result { | |
if let Some(lang) = lang { | |
if !["en", "zh_cn", "ja", "fr"].contains(&lang.as_str()) { | |
return Err(garde::Error::new("unsupported language")); | |
} | |
} | |
Ok(()) | |
} | |
} |
Summary by CodeRabbit
Release Notes
Documentation
README.md
to reflect changes in the command for generating local documentation, now including private items.New Features
Bug Fixes
Refactor