Skip to content
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

refactor(api_apub): update openapi docs #71

Merged
merged 5 commits into from
Sep 28, 2024
Merged

refactor(api_apub): update openapi docs #71

merged 5 commits into from
Sep 28, 2024

Conversation

kwaa
Copy link
Member

@kwaa kwaa commented Sep 28, 2024

fix #66

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced new API endpoints for posts and user inbox activities.
    • Added pagination support for user followers and following endpoints.
    • Implemented new data structures for collections and collection pages.
  • Improvements

    • Enhanced OpenAPI documentation with new paths and components.
    • Streamlined response handling for user-related endpoints.
    • Updated routing logic for user-related handlers for improved clarity.
  • Bug Fixes

    • Adjusted visibility of the notice module to make it publicly accessible.

@kwaa kwaa added documentation Improvements or additions to documentation enhancement New feature or request labels Sep 28, 2024
Copy link
Contributor

coderabbitai bot commented Sep 28, 2024

Walkthrough

The changes encompass multiple modifications across various files in the crates/api_apub and crates/backend directories. Key updates include the introduction of new API endpoints, adjustments to module visibility, the addition of pagination structures, and enhancements to OpenAPI documentation. New data structures such as Collection, CollectionPage, and CollectionOrPage have been defined to improve data handling. Additionally, existing functions have been modified to enforce pagination requirements and streamline response types.

Changes

Files Change Summary
crates/api_apub/src/lib.rs, crates/api_apub/src/posts/mod.rs Added new imports and updated OpenAPI paths and components. Changed notice module visibility from private to public.
crates/api_apub/src/posts/notice.rs Introduced a new API endpoint to retrieve posts using base64-encoded URLs, with detailed response specifications.
crates/api_apub/src/users/mod.rs Added a new Pagination struct and streamlined route definitions using the routes! macro.
crates/api_apub/src/users/user_followers.rs, crates/api_apub/src/users/user_following.rs, crates/api_apub/src/users/user_inbox.rs, crates/api_apub/src/users/user_outbox.rs Updated handler functions to require pagination and changed return types to use CollectionOrPage. Adjusted pagination logic for better handling of responses.
crates/apub/src/collections/collection.rs, crates/apub/src/collections/collection_page.rs, crates/apub/src/collections/mod.rs Introduced new Collection and CollectionPage structs, along with a new CollectionOrPage enum to represent collections and pages flexibly. Removed previous struct definitions.
crates/backend/src/openapi.rs Simplified the OpenApi struct definition by removing specific path specifications, resulting in a more concise attribute structure.

Assessment against linked issues

Objective Addressed Explanation
Write utoipa documentation for apub posts (#66) No documentation for commented-out routes was added.

Possibly related PRs

  • feat: block instances and actors #67: Introduces new imports for Collection, CollectionOrPage, and CollectionPage, which are referenced in other data structures, indicating a direct relationship in terms of data handling.

Poem

🐇 In the meadow where code does play,
New paths and structs brighten the day.
With pagination hops, we leap and bound,
In collections and pages, joy is found.
So let’s celebrate with a happy cheer,
For the changes that bring us all near! 🌼


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?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

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)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🧹 Outside diff range and nitpick comments (10)
crates/api_apub/src/users/user_inbox.rs (1)

12-25: OpenAPI documentation is well-structured and comprehensive.

The OpenAPI documentation for the user inbox endpoint is clear and covers all necessary aspects:

  • HTTP method (POST) and path are correctly specified.
  • Responses include appropriate status codes (OK, NOT_FOUND, INTERNAL_SERVER_ERROR).
  • The parameter for "user" is well-described.

Consider adding a brief description of the endpoint's purpose at the beginning of the documentation, e.g.:

/// User inbox
/// 
/// Handles incoming activities for a user's inbox.
#[utoipa::path(
    // ... (rest of the documentation)
)]

This would provide a quick overview of the endpoint's functionality.

crates/api_apub/src/posts/notice.rs (1)

19-19: Consider removing #[debug_handler] for production use.

The #[debug_handler] attribute is typically used for debugging purposes. If this endpoint is intended for production use, consider removing this attribute to ensure optimal performance and avoid any potential debug-related side effects.

crates/api_apub/src/users/mod.rs (2)

2-3: LGTM! Consider adding documentation for the Pagination struct.

The new Pagination struct and its imports look good. The struct is correctly derived from Deserialize and IntoParams, which are appropriate for query parameters and OpenAPI documentation.

Consider adding documentation comments to the Pagination struct and its page field to provide more context for API users. For example:

/// Represents pagination parameters for API requests.
#[derive(Deserialize, IntoParams)]
pub struct Pagination {
    /// The page number to retrieve. If not provided, defaults to the first page.
    page: Option<u64>,
}

Also applies to: 13-16


21-24: LGTM! Consider updating fallback routes for consistency.

The updated routing logic using the routes! macro improves code readability and aligns well with the OpenAPI documentation approach. This change maintains the same functionality while making the code more concise.

For consistency, consider updating the fallback routes to use the routes! macro as well. This would make the entire routes() function more uniform. Here's an example of how you could refactor the fallback routes:

pub fn routes() -> OpenApiRouter {
    OpenApiRouter::with_openapi(ApubApi::openapi())
        .routes(routes!(
            user::handler,
            user_followers::handler,
            user_following::handler,
            user_inbox::handler,
            user_outbox::handler,
            user::redirect,
            user_followers::redirect,
            user_following::redirect,
            user_outbox::redirect,
            user_inbox::handler
        ))
}

This change would require updating the handler functions to include the appropriate path and method attributes, but it would result in a more consistent and maintainable routing structure.

crates/api_apub/src/lib.rs (1)

29-32: LGTM: New OpenAPI components added.

The addition of Collection, CollectionOrPage, CollectionPage<Url>, and CollectionPage<Value> components enhances the API's schema definitions, supporting improved collection and pagination handling.

Consider adding brief documentation comments for these new components to explain their purpose and usage within the API. This will help other developers understand how to use these structures correctly.

crates/apub/src/collections/collection.rs (1)

9-25: LGTM: Well-structured Collection struct with appropriate attributes.

The Collection struct is well-defined and aligns with the ActivityPub OrderedCollection object. The use of derive macros and serde attributes demonstrates good practices for API development and serialization.

Consider adding doc comments (///) for each field to provide more detailed descriptions. This would enhance the generated documentation and make the struct's purpose clearer to other developers. For example:

/// Represents an ActivityPub OrderedCollection
#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct Collection {
    /// The type of the collection, always "OrderedCollection"
    #[serde(rename = "type")]
    kind: OrderedCollectionType,

    /// The unique identifier for the collection
    /// example: https://hatsu.local/users/example.com/collection
    id: Url,

    // ... (add similar comments for other fields)
}
crates/apub/src/collections/collection_page.rs (2)

9-28: LGTM: Well-structured CollectionPage definition with appropriate attributes.

The CollectionPage<T> struct is well-designed and aligns with the ActivityPub protocol's collection page structure. The use of generics provides flexibility, and the serde attributes are correctly applied for JSON serialization control.

Consider adding documentation comments (///) for the struct and its fields to improve code readability and generate more comprehensive API documentation.


30-57: LGTM: Solid implementation of CollectionPage constructor with proper pagination handling.

The new method effectively constructs a CollectionPage instance, handling pagination logic correctly. The use of Result for error handling is commendable.

  1. Consider translating the Chinese comment on line 41 to English for consistency.
  2. It might be beneficial to add input validation for the page parameter to ensure it's not greater than total_pages.

Consider extracting the URL generation logic for prev and next into separate private methods to improve readability and maintainability. For example:

impl<T> CollectionPage<T> {
    fn generate_prev_url(&self, collection_id: &Url, page: u64) -> Result<Option<Url>, AppError> {
        if page > 1 {
            Some(generate_collection_page_url(collection_id, page - 1)).transpose()
        } else {
            Ok(None)
        }
    }

    fn generate_next_url(&self, collection_id: &Url, page: u64, total_pages: u64) -> Result<Option<Url>, AppError> {
        if page < total_pages {
            Some(generate_collection_page_url(collection_id, page + 1)).transpose()
        } else {
            Ok(None)
        }
    }

    pub fn new(
        collection_id: Url,
        total_items: u64,
        ordered_items: Vec<T>,
        total_pages: u64,
        page: u64,
    ) -> Result<Self, AppError> {
        Ok(Self {
            kind: OrderedCollectionPageType::OrderedCollectionPage,
            id: Url::parse_with_params(collection_id.as_ref(), &[("page", page.to_string())])?,
            prev: self.generate_prev_url(&collection_id, page)?,
            next: self.generate_next_url(&collection_id, page, total_pages)?,
            part_of: collection_id,
            ordered_items,
            total_items,
        })
    }
}

This refactoring improves readability and makes the new method more concise.

crates/api_apub/src/users/user_following.rs (1)

27-27: Clarify the parameter description for 'user'.

The description currently reads "The Domain of the User in the database." If name represents the username, consider updating the description to "The username of the user." This provides clearer information for API consumers.

Apply this diff to update the description:

-            ("user" = String, Path, description = "The Domain of the User in the database."),
+            ("user" = String, Path, description = "The username of the user."),
crates/api_apub/src/users/user_outbox.rs (1)

41-41: Consider providing a default value for pagination.

The pagination parameter is now required in the handler function. Consider providing a default value for the Pagination struct to avoid breaking existing clients that may not provide pagination parameters.

Apply this diff to provide a default value for Pagination:

-    pagination: Query<Pagination>,
+    pagination: Option<Query<Pagination>>,

Then, update the usage of pagination in the handler function:

-    match pagination.page {
+    match pagination.as_ref().map(|p| p.page).unwrap_or(None) {
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between a33a262 and ea87c6e.

📒 Files selected for processing (12)
  • crates/api_apub/src/lib.rs (2 hunks)
  • crates/api_apub/src/posts/mod.rs (1 hunks)
  • crates/api_apub/src/posts/notice.rs (1 hunks)
  • crates/api_apub/src/users/mod.rs (2 hunks)
  • crates/api_apub/src/users/user_followers.rs (4 hunks)
  • crates/api_apub/src/users/user_following.rs (1 hunks)
  • crates/api_apub/src/users/user_inbox.rs (1 hunks)
  • crates/api_apub/src/users/user_outbox.rs (4 hunks)
  • crates/apub/src/collections/collection.rs (1 hunks)
  • crates/apub/src/collections/collection_page.rs (1 hunks)
  • crates/apub/src/collections/mod.rs (2 hunks)
  • crates/backend/src/openapi.rs (1 hunks)
🔇 Additional comments (29)
crates/backend/src/openapi.rs (1)

4-4: Clarify the removal of API paths from OpenAPI documentation

The paths attribute has been removed from the #[openapi] macro. While this simplifies the struct declaration, it raises some concerns:

  1. The API endpoints, specifically hatsu_api_apub::posts::post::post, are no longer explicitly documented here.
  2. This change might not fully address the goal of writing utoipa documentation for apub posts (issue Write utoipa documentation for apub posts #66).

Could you please clarify:

  1. Where are the API endpoints now documented?
  2. How does this change align with the objective of improving documentation for apub posts?

Consider adding a comment explaining the rationale behind this change and directing readers to where they can find the complete API documentation.

To ensure we haven't missed any API documentation, let's search for other potential locations:

✅ Verification successful

API Paths Documentation is Distributed Across Modules

The removal of the paths attribute from the #[openapi] macro in crates/backend/src/openapi.rs appears to be intentional and aligns with the distributed approach to API documentation.

Based on the search results:

  • API endpoints are documented using #[utoipa::path] and #[openapi] annotations in multiple files across different crates.
  • This modular documentation strategy ensures that each module maintains its own API definitions, enhancing maintainability and clarity.

Therefore, the change does not compromise the API documentation but rather organizes it more effectively.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for OpenAPI or utoipa documentation in other files
rg --type rust -e '#\[openapi' -e '#\[utoipa::path' -e 'impl utoipa::OpenApi'

Length of output: 1984

crates/api_apub/src/posts/mod.rs (2)

Line range hint 9-15: LGTM! Verify OpenAPI documentation for the routes.

The routing configuration correctly includes the notice route and maintains the existing routes for posts. The use of OpenApiRouter with ApubApi::openapi() suggests that these routes are documented in the OpenAPI specification.

To ensure that the OpenAPI documentation is up-to-date with these routes, please run the following script:

#!/bin/bash
# Description: Check for OpenAPI documentation of the routes

# Search for OpenAPI documentation related to these routes
rg --type rust "utoipa::path" -A 10 -g "crates/api_apub/src/**/*.rs"

Review the output to confirm that all routes (/notice/*notice, /posts/*post, and /p/*post) are properly documented in the OpenAPI specification.


7-7: LGTM! Verify the usage of the notice module.

The notice module is now public, which aligns with the PR objectives of updating the OpenAPI documentation. This change allows other parts of the crate or external crates to access its contents.

To ensure this change is intentional and properly utilized, please run the following script to check for any usage of the notice module outside its original scope:

If there are no results, consider whether making the module public is necessary for future use or documentation purposes.

✅ Verification successful

Please run the following corrected script to check for any usage of the notice module outside its original scope:


Verified: The notice module is used outside its original scope.

  • Usage found in crates/api_apub/src/lib.rs
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usage of the `notice` module outside its original scope

# Search for imports of the notice module
rg --type rust "use .*notice" --glob '!crates/api_apub/src/posts/mod.rs'

# Search for direct usage of the notice module
rg --type rust "posts::notice" --glob '!crates/api_apub/src/posts/mod.rs'

Length of output: 6470


Script:

# 
#!/bin/bash
# Description: Check for usage of the `notice` module outside its original scope

# Search for imports of the notice module excluding the target file
rg --type rust "use\s+.*notice" --glob '!crates/api_apub/src/posts/mod.rs'

# Search for direct usage of the notice module excluding the target file
rg --type rust "posts::notice" --glob '!crates/api_apub/src/posts/mod.rs'

Length of output: 208

crates/api_apub/src/users/user_inbox.rs (3)

Line range hint 1-10: Imports look good and cover all necessary dependencies.

The imports are comprehensive and include all required dependencies for the new handler function. The addition of TAG from the crate root is appropriate for use in the OpenAPI documentation.


Line range hint 26-29: Handler function implementation looks correct and aligns with documentation.

The handler function is well-implemented:

  • It's correctly marked with #[debug_handler] for development purposes.
  • The function signature matches the OpenAPI documentation.
  • The use of receive_activity with appropriate generic types (WithContext<UserInboxActivities>, ApubUser, AppData) is correct for handling user inbox activities.

Line range hint 1-29: Overall, the changes successfully implement and document the user inbox endpoint.

This implementation aligns well with the PR objectives of updating OpenAPI documentation for the API. The new endpoint for handling user inbox activities is properly implemented and thoroughly documented using utoipa. The changes enhance the API's functionality and improve its documentation, making it easier for developers to understand and use the user inbox feature.

crates/api_apub/src/posts/notice.rs (2)

1-18: LGTM: Imports and OpenAPI documentation are well-structured.

The imports are appropriate for the functionality, and the OpenAPI documentation is comprehensive. It correctly specifies the HTTP method, path, expected responses, and parameters. The use of the TAG constant suggests consistent tagging across the API, which is a good practice.


Line range hint 20-32: LGTM: Function implementation is robust and efficient.

The implementation correctly handles base64 decoding and URL validation. The use of base64_simd for decoding is a good choice for performance. The error handling is appropriate, returning a not found error for invalid inputs.

However, please verify that the redirect URL format /posts/{url} is correct and consistent with the rest of the API. Run the following script to check for similar redirect patterns:

✅ Verification successful

Please run the following script to further verify the route definitions for /posts/ in the codebase:


Verified: Redirect URL format /posts/{url} is consistent with existing route definitions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for similar redirect patterns in the codebase

# Search for Redirect::permanent calls
echo "Searching for Redirect::permanent calls:"
rg --type rust 'Redirect::permanent\(' -A 1

# Search for route definitions with '/posts/' prefix
echo "Searching for route definitions with '/posts/' prefix:"
rg --type rust '#\[utoipa::path\(.*path\s*=\s*"/posts/.*"\)' -A 5

Length of output: 1392


Script:

#!/bin/bash
# Description: Further verify route definitions with '/posts/' prefix by broadening the search pattern

# Search for utoipa::path attributes with '/posts/' in any format
echo "Searching for utoipa::path attributes with '/posts/' prefix:"
rg --type rust '\\#\\[utoipa::path.*path\\s*=\\s*".*/posts/.*"\\]' -A 5

# Additionally, search for any route annotations that might define '/posts/' paths
echo "Searching for any route definitions containing '/posts/':"
rg --type rust 'path\s*=\s*".*/posts/.*"' -A 5

Length of output: 797

crates/api_apub/src/users/mod.rs (1)

Line range hint 1-31: Overall changes align well with PR objectives.

The modifications in this file, including the introduction of the Pagination struct and the use of the routes! macro, contribute significantly to improving the API documentation and code maintainability. These changes directly address the PR's objective of updating OpenAPI documentation for the API.

The Pagination struct provides a clear structure for handling paginated requests, while the routes! macro simplifies the routing logic, making it more readable and easier to maintain. Both of these changes will result in better-documented and more understandable API endpoints.

crates/api_apub/src/lib.rs (2)

3-3: LGTM: New imports align with OpenAPI updates.

The added imports for Collection, CollectionOrPage, CollectionPage, Value, and Url are consistent with the new OpenAPI components and likely support the expanded API functionality.

Also applies to: 7-8


Line range hint 1-53: LGTM: File structure and changes are consistent and well-integrated.

The modifications to this file are well-structured and align with the PR objectives. The new imports, OpenAPI paths, and components are integrated seamlessly with the existing code. The overall file structure remains consistent and maintainable.

crates/apub/src/collections/collection.rs (2)

1-7: LGTM: Imports are appropriate and well-organized.

The imports cover all necessary dependencies for implementing an ActivityPub collection, including serialization, URL handling, and OpenAPI documentation generation. The local import of generate_collection_page_url suggests good modularization of the codebase.


1-50: Summary: Good implementation of ActivityPub Collection, aligns with PR objectives

This new file introduces a well-structured Collection struct and its implementation, which aligns with the ActivityPub protocol specifications. The code contributes to the PR's objective of updating OpenAPI docs (via the ToSchema derive) and addresses issue #66 by providing a foundation for handling ActivityPub collections in the API.

The implementation is generally solid, with good use of Rust features and external crates. We've suggested a few minor improvements:

  1. Adding more detailed documentation comments to the struct fields.
  2. Fixing a small logic issue in the last page URL generation.
  3. Adding input validation in the new method to ensure consistency between total_items and total_pages.

These changes will enhance the robustness and clarity of the code, further supporting the PR's objectives.

crates/apub/src/collections/collection_page.rs (2)

1-8: LGTM: Imports are appropriate and well-organized.

The imports cover all necessary dependencies for the implementation, including ActivityPub federation types, error handling, serialization, URL manipulation, and OpenAPI documentation generation.


1-57: Summary: CollectionPage implementation aligns well with PR objectives

This new file introduces a CollectionPage struct and its implementation, which directly contributes to the PR's objective of updating OpenAPI documentation and enhancing the API's collection handling capabilities. The code is well-structured and aligns with ActivityPub protocol requirements.

The implementation of CollectionPage provides a solid foundation for documenting and handling paginated collections, which is crucial for addressing issue #66 ("Write utoipa documentation for apub posts"). The use of the ToSchema derive macro ensures that this struct can be easily integrated into the OpenAPI documentation.

While the implementation is generally strong, consider the suggested improvements to further enhance code quality and maintainability:

  1. Add documentation comments for the struct and its fields.
  2. Translate the Chinese comment to English for consistency.
  3. Consider refactoring the URL generation logic for improved readability.

These changes will further improve the codebase and make it easier for other developers to understand and maintain the API documentation.

crates/api_apub/src/users/user_following.rs (2)

34-34: Ensure 'Pagination' handles default values for missing query parameters.

By changing the handler's signature from accepting an optional Query<Pagination> to a mandatory Query<Pagination>, it's important to ensure that Pagination can handle cases where query parameters are not provided by clients. This ensures backward compatibility and prevents potential errors when clients omit pagination parameters.

Run the following script to verify that Pagination handles default values:


39-54: ⚠️ Potential issue

Verify the correctness of URL construction in 'Collection' and 'CollectionPage'.

The URLs are constructed by joining generate_user_url(data.domain(), &name)? with &format!("{name}/following"). There is a potential risk of duplicating the username in the URL, resulting in incorrect URLs like https://example.com/users/username/username/following. Ensure that the URL construction results in the correct endpoint.

Run the following script to check the generated URLs for a sample user:

✅ Verification successful

URL construction is correct and does not duplicate the username.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify that URL generation does not duplicate the username.

# Test: Print the generated URLs for a sample username and inspect the output.
echo "Testing URL generation for user 'alice':"
echo "Base URL:"
hatsu_utils_url=$(rg --no-heading --no-filename --type rust 'fn generate_user_url' -A 10 | grep -Po '(?<=return ).*(?=;)')
echo "$hatsu_utils_url"

echo "Generated URL:"
echo "$hatsu_utils_url.join(\"alice/following\")"

Length of output: 361


Script:

#!/bin/bash
# Description: Extract the implementation of `generate_user_url` function.

# Find the file where `generate_user_url` is defined
file_path=$(rg --files-with-matches 'fn generate_user_url' --type rust | head -n 1)

if [ -z "$file_path" ]; then
  echo "generate_user_url function not found in the codebase."
  exit 1
fi

echo "Implementation of generate_user_url in $file_path:"
rg --before-context=5 --after-context=20 'fn generate_user_url' "$file_path"

Length of output: 1121


Script:

#!/bin/bash
# Description: Extract all return statements within `generate_user_url` function.

# Find the file where `generate_user_url` is defined
file_path=$(rg --files-with-matches 'fn generate_user_url' --type rust | head -n 1)

if [ -z "$file_path" ]; then
  echo "generate_user_url function not found in the codebase."
  exit 1
fi

echo "Return statements in generate_user_url:"
rg --no-heading --no-filename 'return .*;' "$file_path" | grep 'fn generate_user_url' -A 10

Length of output: 353


Script:

#!/bin/bash
# Description: Extract the URL format string used in `Url::parse` within `generate_user_url`.

# Find the file where `generate_user_url` is defined
file_path=$(rg --files-with-matches 'fn generate_user_url' --type rust | head -n 1)

if [ -z "$file_path" ]; then
  echo "generate_user_url function not found in the codebase."
  exit 1
fi

echo "URL format strings in generate_user_url:"
rg --no-heading --no-filename 'Url::parse(&format!' "$file_path" | grep -Po '(?<=")[^"]+'

Length of output: 434


Script:

#!/bin/bash
# Description: Check for instances where the username might be duplicated in URL construction.

# Find the file where `generate_user_url` is defined
file_path=$(rg --files-with-matches 'fn generate_user_url' --type rust | head -n 1)

if [ -z "$file_path" ]; then
  echo "generate_user_url function not found in the codebase."
  exit 1
fi

echo "Checking for potential username duplication in URL construction:"
rg --no-heading --no-filename 'generate_user_url' "$file_path" | rg 'join'

Length of output: 382


Script:

#!/bin/bash
# Description: Extract the format strings used in `Url::parse` within `generate_user_url`.

# Find the file where `generate_user_url` is defined
file_path=$(rg --files-with-matches 'fn generate_user_url' --type rust | head -n 1)

if [ -z "$file_path" ]; then
  echo "generate_user_url function not found in the codebase."
  exit 1
fi

echo "Format strings used in Url::parse within generate_user_url:"
rg --no-heading --no-filename 'Url::parse\s*\(&\s*format!' "$file_path" | grep -Po '".+?"'

Length of output: 471


Script:

#!/bin/bash
# Description: Analyze URL concatenation in user_following.rs to check for username duplication.

# File to analyze
target_file="crates/api_apub/src/users/user_following.rs"

if [ ! -f "$target_file" ]; then
  echo "File $target_file does not exist."
  exit 1
fi

echo "Analyzing URL concatenation in $target_file:"
rg 'generate_user_url' "$target_file" | rg 'join' --context=2

Length of output: 368

crates/api_apub/src/users/user_followers.rs (6)

23-36: Great job documenting the API endpoint!

The utoipa documentation provides clear information about the endpoint, including the HTTP method, path, responses, and parameters. This will greatly enhance the usability and understanding of the API.


40-40: Verify the impact of changing Option<Query<Pagination>> to Query<Pagination>.

Changing the parameter type from Option<Query<Pagination>> to Query<Pagination> means that the pagination query parameter is now required. Ensure that this change is intentional and that all callers of this endpoint have been updated to provide the necessary pagination information.

Run the following script to verify the usage of the handler function:

#!/bin/bash
# Description: Verify the usage of the `handler` function.

# Test: Search for calls to the `handler` function. 
# Expect: All calls provide the required `pagination` argument.
rg --type rust -A 5 $'user_followers::handler'

21-21: Verify the import of Pagination from the users module.

Ensure that the Pagination struct is defined correctly in the users module and that the import statement is valid.

Run the following script to verify the import:

#!/bin/bash
# Description: Verify the import of `Pagination` from the `users` module.

# Test: Search for the `Pagination` struct definition in the `users` module.
# Expect: The struct definition exists.
rg --type rust -A 5 $'struct Pagination' crates/api_apub/src/users

42-42: Verify the usage of FederationJson<WithContext<CollectionOrPage>> in the codebase.

The return type of the handler has been updated to Result<FederationJson<WithContext<CollectionOrPage>>, AppError>. Ensure that all code paths that call this handler are expecting and handling the new return type correctly.

Run the following script to verify the usage of the new return type:

#!/bin/bash
# Description: Verify the usage of `FederationJson<WithContext<CollectionOrPage>>` in the codebase.

# Test: Search for the new return type. 
# Expect: Usage in relevant code paths that call the `handler` function.
rg --type rust -A 5 $'FederationJson<WithContext<CollectionOrPage>>'

58-63: Verify the construction of CollectionOrPage::Collection.

Ensure that the Collection variant of CollectionOrPage is constructed correctly, with the appropriate URL, total items, and total pages. Verify that the URL generation logic is correct and handles any potential errors.

Run the following script to verify the Collection construction:

#!/bin/bash
# Description: Verify the construction of `CollectionOrPage::Collection`.

# Test: Search for the construction of `CollectionOrPage::Collection`. 
# Expect: Correct URL generation and handling of potential errors.
rg --type rust -A 5 $'CollectionOrPage::Collection'

Line range hint 73-86: Verify the construction of CollectionOrPage::CollectionPageUrl.

Ensure that the CollectionPageUrl variant of CollectionOrPage is constructed correctly, with the appropriate URL, total items, page items, total pages, and current page. Verify that the URL generation logic is correct and handles any potential errors. Also, ensure that the follower_pages pagination logic is correct and fetches the desired page of followers.

Run the following script to verify the CollectionPageUrl construction:

#!/bin/bash
# Description: Verify the construction of `CollectionOrPage::CollectionPageUrl`.

# Test: Search for the construction of `CollectionOrPage::CollectionPageUrl`. 
# Expect: Correct URL generation, pagination logic, and handling of potential errors.
rg --type rust -A 10 $'CollectionOrPage::CollectionPageUrl'
crates/api_apub/src/users/user_outbox.rs (6)

24-37: Great job documenting the API endpoint!

The utoipa documentation for the user outbox endpoint is comprehensive and follows the OpenAPI specification. It clearly describes the endpoint, its parameters, and the expected responses.


43-43: Verify the usage of CollectionOrPage in the response.

The return type of the handler function has been updated to use CollectionOrPage in the response. Ensure that the code constructing the response correctly uses the CollectionOrPage enum variants.

Manually review the code constructing the response to ensure the correct usage of CollectionOrPage enum variants.


61-66: LGTM!

The usage of CollectionOrPage::Collection variant for constructing the response when no pagination is provided is correct.


Line range hint 76-92: LGTM!

The usage of CollectionOrPage::CollectionPageValue variant for constructing the response when a specific page is requested is correct. The pagination logic handles the case when the requested page is out of bounds and returns an appropriate error.


22-22: Verify the import of Pagination struct.

The Pagination struct is now imported from another module. Ensure that the struct definition in the source module matches the usage in this file.

Run the following script to verify the Pagination struct definition:

✅ Verification successful

Import of Pagination struct verified successfully.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the `Pagination` struct definition.

# Test: Search for the `Pagination` struct definition. Expect: Struct definition that matches the usage.
rg --type rust -A 5 $'struct Pagination'

Length of output: 376


Script:

#!/bin/bash
# Description: Verify usages of the `Pagination` struct in user_outbox.rs.

# Search for all instances where `Pagination` is used.
rg --type rust 'Pagination' crates/api_apub/src/users/user_outbox.rs -A 5

Length of output: 571


15-15: Verify the usage of CollectionOrPage in the codebase.

The introduction of the CollectionOrPage enum is a good change as it allows the handler to return either a full collection or a paginated page. However, ensure that the code consuming this API endpoint is updated to handle both variants of the enum.

Run the following script to verify the usage of CollectionOrPage:

crates/api_apub/src/lib.rs Show resolved Hide resolved
crates/apub/src/collections/collection.rs Outdated Show resolved Hide resolved
crates/apub/src/collections/mod.rs Show resolved Hide resolved
crates/api_apub/src/users/user_followers.rs Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🧹 Outside diff range and nitpick comments (21)
crates/backend/src/openapi.rs (1)

Line range hint 1-6: Summary of changes and potential impact

The modifications to the ApiDoc struct definition simplify the OpenAPI documentation generation. While this aligns with the PR objectives, it's crucial to ensure that all necessary API endpoints are still properly documented.

To maintain comprehensive API documentation:

  1. Verify that the removed hatsu_api_apub::posts::post::post path is documented elsewhere or intentionally excluded.
  2. Ensure that this change doesn't result in missing documentation for any critical API endpoints.
  3. Consider adding a comment explaining the rationale behind this simplification for future maintainers.

Consider implementing a centralized approach to manage OpenAPI documentation across the project. This could involve:

  1. Creating a dedicated module for OpenAPI configuration.
  2. Implementing a custom procedural macro to automatically include all relevant paths and components.
  3. Establishing clear guidelines for documenting new API endpoints to maintain consistency and completeness in the OpenAPI specification.
crates/api_apub/src/posts/mod.rs (2)

Line range hint 10-16: Enhance OpenAPI documentation for routes.

While the routing configuration is correct, consider adding explicit OpenAPI documentation for each route using Utoipa attributes. This will improve the clarity and completeness of the API documentation.

Example of how to add documentation:

/// Get a notice
#[utoipa::path(
    get,
    path = "/notice/{notice}",
    responses(
        (status = 200, description = "Notice found", body = Notice),
        (status = 404, description = "Notice not found")
    ),
    params(
        ("notice" = String, Path, description = "Notice identifier")
    )
)]
async fn notice(/* ... */) -> impl IntoResponse {
    // ...
}

Apply similar documentation to the post and redirect routes as well.


Line range hint 1-16: Summary: Good progress, but further documentation enhancements recommended.

The changes in this file contribute to the PR objective of updating OpenAPI documentation for the apub module. The notice module is now public, which should allow for better API documentation. However, to fully meet the PR objectives:

  1. Add explicit OpenAPI documentation for each route using Utoipa attributes.
  2. Clarify the status of the Utoipa documentation task that was mentioned in the removed comment.
  3. Verify that making the notice module public doesn't unintentionally expose sensitive information.

These steps will ensure comprehensive and accurate API documentation, aligning with the goals outlined in issue #66.

crates/api_apub/src/users/user_inbox.rs (2)

13-25: LGTM! Consider adding a request body description.

The newly added #[utoipa::path] attribute provides clear and comprehensive documentation for the user inbox endpoint, aligning well with the PR objectives. The path, HTTP method, responses, and parameters are correctly specified.

Consider adding a request_body field to the #[utoipa::path] attribute to describe the expected structure of the incoming activity data. This would provide more complete documentation for API consumers. For example:

#[utoipa::path(
    // ... existing fields ...
    request_body = ActivityData,
    // ... remaining fields ...
)]

Ensure to import or define ActivityData in the OpenAPI schema if it's not already included.


Line range hint 26-30: Verified consistency. Consider adding error handling.

The handler function implementation is consistent with the newly added OpenAPI documentation. The function signature and parameters align well with the documented endpoint.

Consider adding explicit error handling to match the documented NOT_FOUND and INTERNAL_SERVER_ERROR responses. This would improve the robustness of the endpoint and ensure it behaves as documented. For example:

pub async fn handler(data: Data<AppData>, activity_data: ActivityData) -> Result<impl IntoResponse, AppError> {
    receive_activity::<WithContext<UserInboxActivities>, ApubUser, AppData>(activity_data, &data)
        .await
        .map_err(|e| {
            // Log the error
            tracing::error!("Error processing inbox activity: {:?}", e);
            // Map the error to an appropriate AppError variant
            AppError::InternalServerError
        })
}

This change would require updating the return type and adding appropriate error mapping logic.

crates/api_apub/src/posts/notice.rs (2)

6-18: LGTM: Comprehensive OpenAPI documentation added.

The OpenAPI documentation for the new endpoint is well-structured and follows best practices. It correctly specifies the HTTP method, path, responses, and parameters. This aligns well with the objectives of updating the OpenAPI documentation as mentioned in the PR summary.

Consider adding a brief description of the endpoint's functionality in the OpenAPI documentation. For example:

 #[utoipa::path(
     get,
     tag = TAG,
     path = "/notice/{notice}",
+    summary = "Retrieve a post by its base64-encoded URL",
     responses(
         (status = OK, description = "Post", body = Note),
         (status = NOT_FOUND, description = "Post does not exist", body = AppError)
     ),
     params(
         ("notice" = String, Path, description = "Base64 Post Url")
     )
 )]

This addition would provide users with a quick understanding of the endpoint's purpose.


Line range hint 19-31: LGTM: Well-implemented notice function with proper error handling.

The notice function is well-implemented, with appropriate use of base64_simd for efficient decoding and proper error handling. The security check for "https://" URLs is a good practice.

Consider separating the error cases for invalid base64 and invalid URL format. This would provide more specific error messages:

 pub async fn notice(Path(base64_url): Path<String>) -> Result<Redirect, AppError> {
     let base64 = base64_simd::URL_SAFE;

-    base64.decode_to_vec(&base64_url).map_or_else(
-        |_| Err(AppError::not_found("Record", &base64_url)),
-        |utf8_url| match String::from_utf8(utf8_url) {
-            Ok(url) if url.starts_with("https://") =>
-                Ok(Redirect::permanent(&format!("/posts/{url}"))),
-            _ => Err(AppError::not_found("Record", &base64_url)),
-        },
-    )
+    let utf8_url = base64.decode_to_vec(&base64_url)
+        .map_err(|_| AppError::bad_request("Invalid base64 encoding"))?;
+    
+    let url = String::from_utf8(utf8_url)
+        .map_err(|_| AppError::bad_request("Invalid UTF-8 in decoded URL"))?;
+    
+    if url.starts_with("https://") {
+        Ok(Redirect::permanent(&format!("/posts/{url}")))
+    } else {
+        Err(AppError::bad_request("URL must start with https://"))
+    }
 }

This change would provide more specific error messages, improving the API's usability.

crates/api_apub/src/users/mod.rs (3)

13-16: LGTM: Pagination struct added with appropriate traits.

The Pagination struct is well-defined and aligns with the PR objective of updating OpenAPI documentation. The use of Option<u64> for the page field allows for optional pagination, which is a good design choice.

Consider adding a doc comment to explain the purpose and usage of this struct, especially since it's public. For example:

/// Represents pagination parameters for API requests.
/// `page`: Optional page number for paginated results.
#[derive(Deserialize, IntoParams)]
pub struct Pagination {
    pub page: Option<u64>,
}

21-24: LGTM: Routing logic refactored using routes! macro.

The refactoring of route definitions using the routes! macro improves code conciseness while maintaining functionality. This change aligns well with the PR objective of refactoring and updating the API.

For consistency, consider applying the same refactoring to the fallback routes (lines 26-30). This would make the routing logic uniform throughout the function. For example:

pub fn routes() -> OpenApiRouter {
    OpenApiRouter::with_openapi(ApubApi::openapi())
        .routes(routes!(
            user::handler,
            user_followers::handler,
            user_following::handler,
            user_inbox::handler,
            user_outbox::handler,
            user::redirect,
            user_followers::redirect,
            user_following::redirect,
            user_outbox::redirect,
            user_inbox::handler
        ))
}

This suggestion assumes that the routes! macro can handle different HTTP methods (GET and POST) correctly. If not, the current mixed approach might be the best solution.


Line range hint 1-30: Overall assessment: Changes improve code structure and align with PR objectives.

The modifications in this file, including the addition of the Pagination struct and the refactoring of route definitions, contribute positively to the project's goal of updating OpenAPI documentation and improving code structure. The changes are well-implemented and consistent with best practices.

As the project evolves, consider the following architectural suggestions:

  1. Implement a consistent pagination strategy across all relevant endpoints.
  2. Document the pagination behavior in the API documentation to ensure clear understanding for API consumers.
  3. Consider implementing rate limiting alongside pagination to further protect your API from potential abuse.
crates/apub/src/collections/collection.rs (2)

9-25: LGTM: Well-structured Collection struct with a minor suggestion.

The Collection struct is well-defined and aligns with ActivityPub collection requirements. It makes good use of derive macros and serde attributes for serialization and documentation.

Consider adding doc comments (///) instead of regular comments for better documentation:

-    // example: https://hatsu.local/users/example.com/collection
+    /// Example: https://hatsu.local/users/example.com/collection
     id: Url,

-    // example: https://hatsu.local/users/example.com/collection?page=1
+    /// Example: https://hatsu.local/users/example.com/collection?page=1
     first: Url,
-    // example: https://hatsu.local/users/example.com/collection?page=64
+    /// Example: https://hatsu.local/users/example.com/collection?page=64
     #[serde(skip_serializing_if = "Option::is_none")]
     last: Option<Url>,

-    // collection count
+    /// Collection count
     total_items: u64,

This change will improve the generated documentation for the struct.


27-50: LGTM: Well-implemented constructor with a minor suggestion.

The new method is well-implemented, correctly initializing all fields of the Collection struct. It handles the optional total_pages parameter appropriately and uses a helper function for generating page URLs.

Consider simplifying the logic for setting the last field and handling the edge case when total_pages is Some(0):

     pub fn new(
         collection_id: &Url,
         total_items: u64,
         total_pages: Option<u64>,
     ) -> Result<Self, AppError> {
         Ok(Self {
             kind: OrderedCollectionType::OrderedCollection,
             id: collection_id.clone(),
             first: generate_collection_page_url(collection_id, 1)?,
-            last: match total_pages {
-                Some(total_pages) => Some(generate_collection_page_url(
-                    collection_id,
-                    match total_pages {
-                        page if total_pages > 0 => page + 1,
-                        _ => 1,
-                    },
-                )?),
-                None => None,
-            },
+            last: total_pages.filter(|&pages| pages > 0).map(|pages| generate_collection_page_url(collection_id, pages)).transpose()?,
             total_items,
         })
     }

This change simplifies the logic and ensures that last is None when total_pages is 0 or None.

crates/apub/src/collections/collection_page.rs (2)

9-28: LGTM: Well-structured CollectionPage<T> definition with a minor suggestion.

The CollectionPage<T> struct is well-designed and properly annotated for serialization and OpenAPI documentation. The use of generics allows for flexibility in the type of items stored in the collection.

Consider adding doc comments (///) to the struct and its fields to provide more detailed documentation. This will enhance the generated API documentation and improve code readability. For example:

/// Represents a page of an ordered collection.
#[derive(Clone, Debug, Deserialize, Serialize, ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct CollectionPage<T> {
    /// The type of the collection page.
    #[serde(rename = "type")]
    kind: OrderedCollectionPageType,
    /// The URL of the current page.
    id: Url,
    // ... (add similar comments for other fields)
}

30-57: LGTM: Solid implementation with minor suggestions for improvement.

The new method for CollectionPage<T> is well-implemented, handling pagination logic correctly and using proper error handling with Result<Self, AppError>.

Consider the following improvements:

  1. Replace the Chinese comments with English for better accessibility:
// Provide previous page if current page is greater than 1
prev: match page {
    page if page > 1 => Some(generate_collection_page_url(&collection_id, page - 1)?),
    _ => None,
},
// Provide next page if current page is less than total pages
next: match page {
    page if page < total_pages =>
        Some(generate_collection_page_url(&collection_id, page + 1)?),
    _ => None,
},
  1. Add doc comments to the new method to describe its parameters and return value:
/// Creates a new `CollectionPage<T>` instance.
///
/// # Arguments
///
/// * `collection_id` - The URL of the entire collection.
/// * `total_items` - The total number of items in the collection.
/// * `ordered_items` - The items in the current page.
/// * `total_pages` - The total number of pages in the collection.
/// * `page` - The current page number.
///
/// # Returns
///
/// A `Result` containing the new `CollectionPage<T>` instance or an `AppError`.
pub fn new(
    collection_id: Url,
    total_items: u64,
    ordered_items: Vec<T>,
    total_pages: u64,
    page: u64,
) -> Result<Self, AppError> {
    // ... (existing implementation)
}

These changes will improve code readability and documentation.

crates/api_apub/src/users/user_following.rs (1)

Incorrect redirect URL in user_following.rs

The redirect function currently points to /users/{name}/followers, but it should point to /users/{name}/following to maintain consistency with the file's purpose.

🔗 Analysis chain

Line range hint 61-63: Verify the correctness of the redirect URL

The redirect function redirects to /users/{name}/followers, but since this file handles the following endpoint, should the redirect point to /users/{name}/following instead? Please verify whether this is intentional or if it should be corrected to ensure consistency.

To confirm if the redirect URL is correct, you can search for usages of the redirect function and check the intended redirect paths:

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the redirect URL in the `redirect` function.

# Test: Search for the `redirect` function definition and its usage.
rg --type rust 'pub async fn redirect' -A 3

# Test: Check for routes or handlers that might be invoking this redirect.
rg --type rust 'redirect::\(.*\)'

# Expected Result: Ensure that the redirect points to the appropriate URL based on the context.

Length of output: 1904


Script:

#!/bin/bash
# Description: Extract redirect URLs from user_following.rs and verify correctness.

# Extract the redirect URL from user_following.rs
rg --type rust 'pub async fn redirect' crates/api_apub/src/users/user_following.rs -A 2

# Extract all redirect URLs related to user_following to verify consistency
rg --type rust 'Redirect::permanent' crates/api_apub/src/users/user_following.rs

Length of output: 356

crates/api_apub/src/users/user_followers.rs (3)

33-33: Clarify the parameter description for user

The description "The Domain of the User in the database." may be misleading if user represents the username or user ID. Consider updating the description to accurately reflect the nature of the user parameter.


Line range hint 49-49: Address the TODO: Implement ordering by last_refreshed_at

The code currently orders followers by received_follow::Column::Id. Implementing ordering by last_refreshed_at as indicated in the TODO comment will enhance the relevance of the followers list by displaying the most recently updated followers first.

Would you like assistance in updating the ordering to use last_refreshed_at? I can help provide the code to implement this feature.


Line range hint 66-71: Potential logical error in page validation condition

The condition if page > 1 && page > total.number_of_pages might not correctly handle invalid page numbers less than 1. Consider modifying the condition to if page < 1 || page > total.number_of_pages to catch all invalid page numbers and prevent potential errors.

Apply this diff to correct the condition:

-if page > 1 && page > total.number_of_pages {
+if page < 1 || page > total.number_of_pages {
crates/api_apub/src/users/user_outbox.rs (3)

34-34: Clarify the description of the user parameter

The description for the user parameter states: "The Domain of the User in the database." Since user represents the username or identifier, consider updating the description to accurately reflect this. For example:

-("user" = String, Path, description = "The Domain of the User in the database."),
+("user" = String, Path, description = "The username or identifier of the user."),

Line range hint 51-51: Address the TODO: Order activities by last_refreshed_at

There's a TODO comment indicating the need to order activities by last_refreshed_at. Implementing this will ensure that the outbox displays the most recently updated activities first, improving the user experience.

Would you like assistance in implementing this feature, or should a new GitHub issue be created to track this task?


Line range hint 83-89: Handle errors from activity.into_json() explicitly

Using filter_map(Result::ok) ignores any errors returned by activity.into_json(), potentially causing silent data loss if an activity fails to convert. Consider handling errors explicitly to ensure that any issues are logged or communicated appropriately.

Apply this diff to handle errors explicitly:

 .map(|activity| {
     let activity: ApubActivity = activity.into();
-    activity.into_json()
+    match activity.into_json() {
+        Ok(json) => Some(json),
+        Err(err) => {
+            // Log the error or handle it accordingly
+            eprintln!("Error converting activity to JSON: {:?}", err);
+            None
+        }
+    }
 })
-.filter_map(Result::ok)
 .filter_map(|json| json)
 .collect(),

Alternatively, you could collect the errors and decide on a strategy, such as failing the request or returning partial results with warnings.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between a33a262 and ea87c6e.

📒 Files selected for processing (12)
  • crates/api_apub/src/lib.rs (2 hunks)
  • crates/api_apub/src/posts/mod.rs (1 hunks)
  • crates/api_apub/src/posts/notice.rs (1 hunks)
  • crates/api_apub/src/users/mod.rs (2 hunks)
  • crates/api_apub/src/users/user_followers.rs (4 hunks)
  • crates/api_apub/src/users/user_following.rs (1 hunks)
  • crates/api_apub/src/users/user_inbox.rs (1 hunks)
  • crates/api_apub/src/users/user_outbox.rs (4 hunks)
  • crates/apub/src/collections/collection.rs (1 hunks)
  • crates/apub/src/collections/collection_page.rs (1 hunks)
  • crates/apub/src/collections/mod.rs (2 hunks)
  • crates/backend/src/openapi.rs (1 hunks)
🔇 Additional comments (17)
crates/api_apub/src/posts/mod.rs (2)

Line range hint 1-16: Clarify status of Utoipa documentation task.

The AI summary mentions that a comment about writing Utoipa documentation has been removed. Could you please clarify:

  1. Has the task of writing Utoipa documentation been completed?
  2. If not, is there a plan or timeline for completing this task?
  3. If it's no longer relevant, why was it decided to remove the documentation task?

This information will help ensure that the PR objectives are fully met and that the API documentation is complete.

To help verify the status of the Utoipa documentation, please run the following script:

#!/bin/bash
# Description: Check for Utoipa documentation in relevant files

# Test: Look for Utoipa path attributes in the posts directory
rg --type rust '#\[utoipa::path' crates/api_apub/src/posts

# Test: Check for any TODO comments related to documentation
rg --type rust 'TODO.*document' crates/api_apub/src/posts

Please review the output to confirm the current state of the Utoipa documentation in the relevant files.


7-7: Approved: Module visibility change enhances API documentation.

The notice module is now public, which aligns with the PR objective of updating OpenAPI documentation. This change allows the module to be referenced in the API docs, potentially improving their completeness and accuracy.

To ensure this change doesn't unintentionally expose internal implementation details, please run the following script:

Please review the output to confirm that only intended elements are exposed and properly documented.

✅ Verification successful

Verified: notice module visibility change is appropriate and does not expose unintended elements.

The notice module is now public without exposing any public functions, structs, enums, or traits. This change aligns with the PR objective of updating OpenAPI documentation and ensures that no internal implementation details are inadvertently exposed.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any new public exports in the notice module
# that might need additional documentation or security review.

# Test: Look for public declarations in the notice module
rg --type rust '^\s*pub\s' crates/api_apub/src/posts/notice.rs

# Test: Check if the notice module is imported in other parts of the codebase
rg --type rust 'use .*posts::notice' -g '!crates/api_apub/src/posts/mod.rs'

Length of output: 399


Script:

#!/bin/bash
# Description: List all public items in the notice module to ensure only intended elements are exposed.

# List public functions
rg --type rust 'pub fn' crates/api_apub/src/posts/notice.rs

# List public structs, enums, and other items
rg --type rust 'pub (struct|enum|trait)' crates/api_apub/src/posts/notice.rs

# Check for documentation comments on public items
rg --type rust 'pub .*?\n\s*///' crates/api_apub/src/posts/notice.rs

Length of output: 403


Script:

#!/bin/bash
# Description: List all public items in the notice module to ensure only intended elements are exposed.

# List public functions
rg --type rust 'pub fn' crates/api_apub/src/posts/notice.rs

# List public structs, enums, and traits
rg --type rust 'pub (struct|enum|trait)' crates/api_apub/src/posts/notice.rs

# Check for documentation comments on public items with multiline mode enabled
rg --type rust -U 'pub .*?\n\s*///' crates/api_apub/src/posts/notice.rs

Length of output: 214

crates/api_apub/src/posts/notice.rs (2)

4-4: LGTM: TAG import added.

The import of the TAG constant from the crate root is appropriate. This constant is likely used for categorizing API endpoints, which aligns with the OpenAPI documentation practices.


Line range hint 1-31: Summary: Excellent implementation of the notice endpoint with comprehensive OpenAPI documentation.

This new endpoint successfully addresses the PR objectives by providing a well-documented and implemented route for retrieving posts by base64-encoded URL. The OpenAPI documentation is thorough, and the implementation includes proper error handling and security checks. The use of base64_simd demonstrates attention to performance.

A few minor suggestions have been made to further improve the code:

  1. Adding a summary to the OpenAPI documentation for quick understanding.
  2. Refactoring the error handling for more specific error messages.

Overall, this is a high-quality addition to the API that aligns well with the project's goals.

crates/api_apub/src/users/mod.rs (1)

2-2: LGTM: Import statement for Deserialize added.

The addition of use serde::Deserialize; is appropriate for the new Pagination struct.

crates/api_apub/src/lib.rs (5)

3-3: LGTM: Import additions are appropriate.

The new imports for Collection, CollectionOrPage, CollectionPage, Value, and Url are necessary for the OpenAPI component additions and align with the PR objective of updating the documentation.

Also applies to: 7-8


Line range hint 1-53: LGTM: Overall structure and consistency maintained.

The changes to this file maintain the existing structure while effectively expanding the API documentation. The additions are consistent with the PR objectives and enhance the overall API capabilities.


Line range hint 1-53: Great job: Changes align well with PR objectives.

The modifications in this file successfully address the PR objective of updating the OpenAPI documentation for the apub module. The additions of new paths and components related to posts align with the requirements outlined in issue #66.

As a final verification step, please run the following script to ensure all required routes are properly documented:

#!/bin/bash
# Description: Verify that all routes in the `posts` module are documented in the OpenAPI specification

# Test: List all route definitions in the posts module
routes=$(rg --type rust -e 'pub fn' crates/api_apub/src/posts | awk '{print $3}' | cut -d'(' -f1)

# Test: Check if each route is included in the OpenAPI specification
for route in $routes; do
  if ! grep -q "$route" crates/api_apub/src/lib.rs; then
    echo "Warning: Route $route is not documented in the OpenAPI specification"
  fi
done

This script will help ensure that all implemented routes in the posts module are properly documented in the OpenAPI specification.


29-32: LGTM: New components added to OpenAPI specification.

The addition of Collection, CollectionOrPage, CollectionPage<Url>, and CollectionPage<Value> components aligns with the PR objective and corresponds to the newly imported types.

To ensure the completeness of the schema definitions, please run the following script:

#!/bin/bash
# Description: Verify the schema definitions for the new components

# Test: Check if the new components have proper schema definitions
rg --type rust -e 'struct Collection' -e 'struct CollectionOrPage' -e 'struct CollectionPage' crates/api_apub/src

# Test: Check if the new components are properly documented with utoipa attributes
rg --type rust -e '#\[derive\(.*Schema.*\)\]' -A 10 -e 'struct Collection' -e 'struct CollectionOrPage' -e 'struct CollectionPage' crates/api_apub/src

20-23: LGTM: New paths added to OpenAPI specification.

The addition of posts::notice::notice and posts::post::post paths aligns with the PR objective of updating the OpenAPI documentation for the apub module.

To ensure the completeness of the implementation, please run the following script:

crates/apub/src/collections/collection.rs (2)

1-7: LGTM: Imports are well-organized and relevant.

The imports cover all necessary dependencies for the implementation, including ActivityPub federation, error handling, serialization, URL handling, and OpenAPI documentation. They follow Rust conventions and are organized logically.


1-50: Overall: Excellent implementation aligning with PR objectives.

This new file introduces a well-structured Collection struct for ActivityPub implementation, which aligns perfectly with the PR objectives of updating OpenAPI documentation for the apub module. The code is clean, well-organized, and follows Rust best practices.

Key strengths:

  1. Proper use of derive macros and serde attributes for serialization and documentation.
  2. Well-implemented constructor method with error handling.
  3. Clear structure that contributes to the goal of documenting the apub module.

The minor suggestions provided earlier will further enhance the code quality and documentation. Great job on this implementation!

crates/apub/src/collections/collection_page.rs (2)

1-8: LGTM: Imports are appropriate and well-organized.

The imports cover all necessary dependencies for implementing the CollectionPage struct and its functionality. The use of the internal generate_collection_page_url function from the parent module is a good practice for code organization.


1-57: Overall assessment: Well-implemented CollectionPage<T> with good alignment to PR objectives.

This new file introduces a robust CollectionPage<T> struct that aligns well with the PR objectives of updating OpenAPI documentation. The implementation provides a solid foundation for handling paginated collections in the API, which is crucial for efficient data retrieval and presentation.

Key strengths:

  1. Proper use of generics for flexibility.
  2. Correct handling of pagination logic.
  3. Good error handling with Result<Self, AppError>.
  4. Appropriate use of serde attributes for JSON serialization.

The suggested improvements (adding doc comments and translating Chinese comments) will further enhance the code quality and documentation. Overall, this addition significantly contributes to the goal of improving the API documentation and functionality.

crates/api_apub/src/users/user_following.rs (3)

17-30: OpenAPI documentation updated to reflect new response type and parameters

The #[utoipa::path] attribute has been correctly updated to document the endpoint with the new CollectionOrPage response type and includes the Pagination parameters. This ensures that the OpenAPI documentation accurately represents the API's current behavior.


34-34: Simplify handler function by accepting Query<Pagination> directly

Changing the handler to accept Query<Pagination> instead of an Option<Query<Pagination>> simplifies the code by removing unnecessary option wrapping. Since Pagination can handle optional page parameters internally, this change makes the handler cleaner and easier to maintain.


36-36: Update return type to reflect new response structure

Updating the return type to Result<FederationJson<WithContext<CollectionOrPage>>, AppError> correctly reflects the new response types being returned by the handler. This ensures type safety and clarity in the function signature.

crates/backend/src/openapi.rs Show resolved Hide resolved
crates/apub/src/collections/mod.rs Show resolved Hide resolved
crates/apub/src/collections/mod.rs Show resolved Hide resolved
crates/api_apub/src/users/user_following.rs Outdated Show resolved Hide resolved
crates/api_apub/src/users/user_followers.rs Show resolved Hide resolved
crates/api_apub/src/users/user_followers.rs Show resolved Hide resolved
crates/api_apub/src/users/user_outbox.rs Show resolved Hide resolved
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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

🧹 Outside diff range and nitpick comments (3)
crates/apub/tests/collections_local.rs (3)

1-8: Consider implementing tests for CollectionPage

There's a TODO comment indicating that tests for CollectionPage are planned. It would be beneficial to implement these tests to ensure comprehensive coverage of the collections module.

Would you like assistance in creating test cases for CollectionPage? I can help draft some test scenarios or open a GitHub issue to track this task.


9-21: LGTM! Consider parameterizing the test for better coverage.

The new_collection test effectively verifies the creation of a Collection instance and checks the correctness of the first and last URLs. Good job on covering this functionality!

To enhance the test's robustness, consider parameterizing it with different input values. This approach would allow testing various scenarios without duplicating code. Here's an example of how you could refactor the test:

use rstest::rstest;

#[rstest]
#[case(100, 10, "https://hatsu.local/collections/test1?page=1", "https://hatsu.local/collections/test1?page=10")]
#[case(50, 5, "https://hatsu.local/collections/test1?page=1", "https://hatsu.local/collections/test1?page=10")]
#[case(9, 10, "https://hatsu.local/collections/test1?page=1", "https://hatsu.local/collections/test1?page=1")]
fn test_new_collection(
    #[case] total_items: usize,
    #[case] items_per_page: usize,
    #[case] expected_first: &str,
    #[case] expected_last: &str
) -> Result<(), AppError> {
    let collection_id = Url::parse("https://hatsu.local/collections/test1")?;
    let collection = Collection::new(&collection_id, total_items, items_per_page)?;

    assert_eq!(collection.first, Url::parse(expected_first)?);
    assert_eq!(collection.last, Url::parse(expected_last)?);

    Ok(())
}

This approach uses the rstest crate to provide multiple test cases, increasing coverage and making the test more flexible.


23-34: LGTM! Consider adding an assertion for total items.

The new_empty_collection test effectively verifies the creation of an empty Collection instance and checks that both first and last URLs point to the same page. This is a good test for the edge case of an empty collection.

To make the test even more robust, consider adding an assertion to verify that the total_items field of the Collection is indeed 0. This would ensure that the Collection::new method correctly sets this field for empty collections. Here's an example of how you could add this assertion:

#[test]
fn new_empty_collection() -> Result<(), AppError> {
    let collection_id = Url::parse("https://hatsu.local/collections/test2")?;
    let collection = Collection::new(&collection_id, 0, 0)?;

    let expected_url = Url::parse("https://hatsu.local/collections/test2?page=1")?;

    assert_eq!(collection.first, expected_url);
    assert_eq!(collection.last, expected_url);
    assert_eq!(collection.total_items, 0);

    Ok(())
}

This additional assertion would provide extra confidence in the correctness of the Collection::new method for empty collections.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between ea87c6e and f5ecbfc.

📒 Files selected for processing (5)
  • crates/api_apub/src/users/user_followers.rs (4 hunks)
  • crates/api_apub/src/users/user_following.rs (1 hunks)
  • crates/api_apub/src/users/user_outbox.rs (4 hunks)
  • crates/apub/src/collections/collection.rs (1 hunks)
  • crates/apub/tests/collections_local.rs (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (4)
  • crates/api_apub/src/users/user_followers.rs
  • crates/api_apub/src/users/user_following.rs
  • crates/api_apub/src/users/user_outbox.rs
  • crates/apub/src/collections/collection.rs
🔇 Additional comments (1)
crates/apub/tests/collections_local.rs (1)

1-34: Good test coverage, consider expanding for comprehensive testing

Overall, this test file provides good coverage for the basic functionality of the Collection struct. The two tests effectively verify the creation of both non-empty and empty collections, which are important scenarios to cover.

To further improve the test suite, consider the following suggestions:

  1. Implement tests for the CollectionPage struct as mentioned in the TODO comment.
  2. Parameterize the new_collection test to cover more scenarios with different input values.
  3. Add assertions to verify other properties of the Collection struct, such as total_items and items_per_page.
  4. Consider adding tests for edge cases or potential error scenarios, such as creating a collection with invalid URLs or inconsistent pagination parameters.

These improvements would enhance the robustness and completeness of your test suite, providing better confidence in the correctness of the collections module.

@kwaa kwaa merged commit f552794 into main Sep 28, 2024
1 check passed
@kwaa kwaa deleted the refactor/api_apub branch September 28, 2024 06:53
@coderabbitai coderabbitai bot mentioned this pull request Oct 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Write utoipa documentation for apub posts
1 participant