@@ -30,20 +30,27 @@ use serde::{Deserialize, Serialize};
3030use std:: net:: SocketAddr ;
3131use html_escape;
3232
33+ /// Request payload for creating a comment
3334#[ derive( Deserialize ) ]
3435pub struct CreateCommentRequest {
36+ /// The actual comment text
3537 content : String ,
36- author : Option < String > , // For guest comments
38+ /// The author's name (optional for guests)
39+ author : Option < String > ,
3740}
3841
42+ /// Query parameters for listing comments with pagination and sorting
3943#[ derive( Deserialize ) ]
4044pub struct CommentListQuery {
45+ /// Maximum number of comments to return (default: 50)
4146 #[ serde( default = "default_comment_limit" ) ]
4247 limit : i64 ,
4348
49+ /// Number of comments to skip for pagination
4450 #[ serde( default ) ]
4551 offset : i64 ,
4652
53+ /// Sorting criteria (e.g., "created_at:desc")
4754 #[ serde( default ) ]
4855 sort : Option < String > ,
4956}
@@ -52,18 +59,30 @@ fn default_comment_limit() -> i64 {
5259 50
5360}
5461
62+ /// Local DTO for comment responses, mapping from the database model
5563#[ derive( Serialize , sqlx:: FromRow ) ]
5664pub struct Comment {
65+ /// Unique identifier for the comment
5766 pub id : String ,
67+ /// Optional parent tutorial ID
5868 pub tutorial_id : Option < String > ,
69+ /// Optional parent post ID
5970 pub post_id : Option < String > ,
71+ /// Display name of the author
6072 pub author : String ,
73+ /// The comment content (HTML escaped)
6174 pub content : String ,
75+ /// RFC3339 formatted creation timestamp
6276 pub created_at : String ,
77+ /// Total number of votes/likes
6378 pub votes : i64 ,
79+ /// Whether the comment was posted by an administrator
6480 pub is_admin : bool ,
6581}
6682
83+ /// Validates and sanitizes comment content
84+ ///
85+ /// Trims whitespace, checks length constraints, and escapes HTML characters.
6786fn sanitize_comment_content ( raw : & str ) -> Result < String , ( StatusCode , Json < ErrorResponse > ) > {
6887 let trimmed = raw. trim ( ) ;
6988
@@ -90,6 +109,9 @@ fn sanitize_comment_content(raw: &str) -> Result<String, (StatusCode, Json<Error
90109 Ok ( sanitized)
91110}
92111
112+ /// Handler for listing comments on a tutorial
113+ ///
114+ /// Returns a paginated list of comments for the specified tutorial.
93115pub async fn list_comments (
94116 State ( pool) : State < DbPool > ,
95117 Path ( tutorial_id) : Path < String > ,
@@ -158,6 +180,9 @@ pub async fn list_comments(
158180 Ok ( Json ( response_comments) )
159181}
160182
183+ /// Handler for creating a comment on a tutorial
184+ ///
185+ /// Validates the tutorial existence and delegates to internal creation logic.
161186pub async fn create_comment (
162187 State ( pool) : State < DbPool > ,
163188 ConnectInfo ( addr) : ConnectInfo < SocketAddr > ,
@@ -193,6 +218,9 @@ pub async fn create_comment(
193218 create_comment_internal ( pool, Some ( tutorial_id) , None , payload, None , addr. ip ( ) . to_string ( ) ) . await
194219}
195220
221+ /// Handler for listing comments on a blog post
222+ ///
223+ /// Returns a paginated list of comments for the specified post.
196224pub async fn list_post_comments (
197225 State ( pool) : State < DbPool > ,
198226 Path ( post_id) : Path < String > ,
@@ -258,6 +286,9 @@ pub async fn list_post_comments(
258286 Ok ( Json ( response_comments) )
259287}
260288
289+ /// Handler for creating a comment on a blog post
290+ ///
291+ /// Supports both authenticated users and guest comments.
261292pub async fn create_post_comment (
262293 State ( pool) : State < DbPool > ,
263294 ConnectInfo ( addr) : ConnectInfo < SocketAddr > ,
@@ -290,6 +321,9 @@ pub async fn create_post_comment(
290321 create_comment_internal ( pool, None , Some ( post_id) , payload, claims, addr. ip ( ) . to_string ( ) ) . await
291322}
292323
324+ /// Internal logic for creating a comment on either a tutorial or a post
325+ ///
326+ /// Handles author resolution (admin/user vs guest), rate limiting, and database insertion.
293327async fn create_comment_internal (
294328 pool : DbPool ,
295329 tutorial_id : Option < String > ,
@@ -435,6 +469,9 @@ async fn create_comment_internal(
435469 Ok ( Json ( response_comment) )
436470}
437471
472+ /// Handler for deleting a comment
473+ ///
474+ /// Requires the user to be either an administrator or the original author.
438475pub async fn delete_comment (
439476 claims : auth:: Claims ,
440477 State ( pool) : State < DbPool > ,
@@ -510,6 +547,9 @@ pub async fn delete_comment(
510547 Ok ( StatusCode :: NO_CONTENT )
511548}
512549
550+ /// Handler for voting on a comment
551+ ///
552+ /// Authenticated users can upvote/downvote comments. Prevention logic ensures one vote per user.
513553pub async fn vote_comment (
514554 State ( pool) : State < DbPool > ,
515555 claims : auth:: Claims ,
0 commit comments