Skip to content

Commit aaa1119

Browse files
committed
Add testimonials CRUD with nested and standalone routes
1 parent 14c565f commit aaa1119

9 files changed

Lines changed: 983 additions & 1 deletion

File tree

src/api/v1/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
pub mod auth;
22
pub mod projects;
3+
pub mod testimonials;

src/api/v1/testimonials/dto.rs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
use rapina::schemars::{self, JsonSchema};
2+
use serde::{Deserialize, Serialize};
3+
4+
#[derive(Deserialize, JsonSchema)]
5+
pub struct CreateTestimonialRequest {
6+
pub author_name: String,
7+
#[serde(rename = "type")]
8+
pub testimonial_type: Option<String>,
9+
pub content: Option<String>,
10+
pub rating: Option<i16>,
11+
pub author_email: Option<String>,
12+
pub author_title: Option<String>,
13+
pub author_avatar_url: Option<String>,
14+
pub author_company: Option<String>,
15+
pub author_url: Option<String>,
16+
pub video_url: Option<String>,
17+
pub video_thumbnail_url: Option<String>,
18+
pub video_duration_seconds: Option<i32>,
19+
pub transcription: Option<String>,
20+
pub source: Option<String>,
21+
pub source_platform: Option<String>,
22+
pub source_url: Option<String>,
23+
pub source_id: Option<String>,
24+
pub sentiment: Option<String>,
25+
pub sentiment_score: Option<f32>,
26+
pub language: Option<String>,
27+
}
28+
29+
#[derive(Deserialize, JsonSchema)]
30+
pub struct UpdateTestimonialRequest {
31+
#[serde(rename = "type")]
32+
pub testimonial_type: Option<String>,
33+
pub content: Option<String>,
34+
pub rating: Option<i16>,
35+
pub author_name: Option<String>,
36+
pub author_email: Option<String>,
37+
pub author_title: Option<String>,
38+
pub author_avatar_url: Option<String>,
39+
pub author_company: Option<String>,
40+
pub author_url: Option<String>,
41+
pub video_url: Option<String>,
42+
pub video_thumbnail_url: Option<String>,
43+
pub video_duration_seconds: Option<i32>,
44+
pub transcription: Option<String>,
45+
pub source: Option<String>,
46+
pub source_platform: Option<String>,
47+
pub source_url: Option<String>,
48+
pub source_id: Option<String>,
49+
pub sentiment: Option<String>,
50+
pub sentiment_score: Option<f32>,
51+
pub language: Option<String>,
52+
pub is_approved: Option<bool>,
53+
pub is_featured: Option<bool>,
54+
}
55+
56+
#[derive(Serialize, JsonSchema)]
57+
pub struct TestimonialResponse {
58+
pub id: String,
59+
pub project_id: String,
60+
#[serde(rename = "type")]
61+
pub testimonial_type: String,
62+
pub content: Option<String>,
63+
pub rating: Option<i16>,
64+
pub author_name: String,
65+
pub author_email: Option<String>,
66+
pub author_title: Option<String>,
67+
pub author_avatar_url: Option<String>,
68+
pub author_company: Option<String>,
69+
pub author_url: Option<String>,
70+
pub video_url: Option<String>,
71+
pub video_thumbnail_url: Option<String>,
72+
pub video_duration_seconds: Option<i32>,
73+
pub transcription: Option<String>,
74+
pub source: Option<String>,
75+
pub source_platform: Option<String>,
76+
pub source_url: Option<String>,
77+
pub source_id: Option<String>,
78+
pub sentiment: Option<String>,
79+
pub sentiment_score: Option<f32>,
80+
pub language: Option<String>,
81+
pub is_approved: bool,
82+
pub is_featured: bool,
83+
pub created_at: String,
84+
pub updated_at: String,
85+
}
86+
87+
#[derive(Deserialize, JsonSchema)]
88+
pub struct ListTestimonialsQuery {
89+
pub is_approved: Option<bool>,
90+
pub is_featured: Option<bool>,
91+
}

src/api/v1/testimonials/error.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
use rapina::database::DbError;
2+
use rapina::prelude::*;
3+
4+
pub enum TestimonialError {
5+
DbError(DbError),
6+
NotFound,
7+
Forbidden,
8+
}
9+
10+
impl IntoApiError for TestimonialError {
11+
fn into_api_error(self) -> Error {
12+
match self {
13+
TestimonialError::DbError(e) => e.into_api_error(),
14+
TestimonialError::NotFound => Error::not_found("testimonial not found"),
15+
TestimonialError::Forbidden => Error::forbidden("you do not own this project"),
16+
}
17+
}
18+
}
19+
20+
impl DocumentedError for TestimonialError {
21+
fn error_variants() -> Vec<ErrorVariant> {
22+
vec![
23+
ErrorVariant {
24+
status: 404,
25+
code: "NOT_FOUND",
26+
description: "Testimonial not found",
27+
},
28+
ErrorVariant {
29+
status: 403,
30+
code: "FORBIDDEN",
31+
description: "User does not own this project",
32+
},
33+
ErrorVariant {
34+
status: 500,
35+
code: "INTERNAL_ERROR",
36+
description: "Internal server error",
37+
},
38+
]
39+
}
40+
}
41+
42+
impl From<DbError> for TestimonialError {
43+
fn from(e: DbError) -> Self {
44+
TestimonialError::DbError(e)
45+
}
46+
}

0 commit comments

Comments
 (0)