Skip to content

Commit 898f3ba

Browse files
Copilotngocbd
andcommitted
Add OpenAPI/Swagger documentation with utoipa for auth and user endpoints
Co-authored-by: ngocbd <439333+ngocbd@users.noreply.github.com>
1 parent 58b30e2 commit 898f3ba

8 files changed

Lines changed: 334 additions & 41 deletions

File tree

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ regex = "1.0"
6262
kube = { version = "0.95", features = ["runtime", "derive"] }
6363
k8s-openapi = { version = "0.23", features = ["latest"] }
6464

65+
# OpenAPI documentation
66+
utoipa = { version = "4.0", features = ["axum_extras", "chrono", "uuid"] }
67+
utoipa-swagger-ui = { version = "4.0", features = ["axum"] }
68+
6569
[dev-dependencies]
6670
tower-test = "0.4"
6771
tempfile = "3.0"

src/auth/models.rs

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,30 @@
11
use chrono::{DateTime, Utc};
22
use serde::{Deserialize, Serialize};
33
use sqlx::FromRow;
4+
use utoipa::ToSchema;
45
use uuid::Uuid;
56
use validator::Validate;
67

7-
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
8+
#[derive(Debug, Clone, FromRow, Serialize, Deserialize, ToSchema)]
89
pub struct User {
910
pub id: Uuid,
1011
pub username: String,
1112
pub email: String,
13+
#[serde(skip_serializing)]
1214
pub password_hash: String,
1315
pub created_at: DateTime<Utc>,
1416
pub updated_at: DateTime<Utc>,
1517
pub last_login: Option<DateTime<Utc>>,
1618
pub is_active: bool,
1719
}
1820

19-
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
21+
#[derive(Debug, Clone, FromRow, Serialize, Deserialize, ToSchema)]
2022
pub struct ApiKey {
2123
pub id: Uuid,
2224
pub user_id: Uuid,
2325
pub name: String,
2426
pub description: Option<String>,
27+
#[serde(skip_serializing)]
2528
pub key_hash: String,
2629
pub key_prefix: String,
2730
pub created_at: DateTime<Utc>,
@@ -30,71 +33,88 @@ pub struct ApiKey {
3033
pub is_active: bool,
3134
}
3235

33-
#[derive(Debug, Deserialize, Validate)]
36+
#[derive(Debug, Deserialize, Validate, ToSchema)]
3437
pub struct RegisterRequest {
38+
/// Username must be between 3 and 50 characters
3539
#[validate(length(min = 3, max = 50))]
3640
pub username: String,
41+
/// Valid email address
3742
#[validate(email)]
3843
pub email: String,
44+
/// Password must be at least 8 characters
3945
#[validate(length(min = 8))]
4046
pub password: String,
47+
/// Must match the password field
4148
pub confirm_password: String,
4249
}
4350

44-
#[derive(Debug, Deserialize, Validate)]
51+
#[derive(Debug, Deserialize, Validate, ToSchema)]
4552
pub struct LoginRequest {
53+
/// Valid email address
4654
#[validate(email)]
4755
pub email: String,
56+
/// User password
4857
pub password: String,
4958
}
5059

51-
#[derive(Debug, Serialize)]
60+
#[derive(Debug, Serialize, ToSchema)]
5261
pub struct AuthResponse {
62+
/// JWT access token
5363
pub access_token: String,
64+
/// JWT refresh token
5465
pub refresh_token: String,
66+
/// Token expiration timestamp
5567
pub expires_at: DateTime<Utc>,
68+
/// User information
5669
pub user: UserInfo,
5770
}
5871

59-
#[derive(Debug, Serialize)]
72+
#[derive(Debug, Serialize, ToSchema)]
6073
pub struct UserInfo {
6174
pub id: Uuid,
6275
pub username: String,
6376
pub email: String,
6477
}
6578

66-
#[derive(Debug, Deserialize)]
79+
#[derive(Debug, Deserialize, ToSchema)]
6780
pub struct RefreshTokenRequest {
81+
/// JWT refresh token
6882
pub refresh_token: String,
6983
}
7084

71-
#[derive(Debug, Serialize)]
85+
#[derive(Debug, Serialize, ToSchema)]
7286
pub struct RefreshTokenResponse {
87+
/// New JWT access token
7388
pub access_token: String,
89+
/// New token expiration timestamp
7490
pub expires_at: DateTime<Utc>,
7591
}
7692

77-
#[derive(Debug, Deserialize, Validate)]
93+
#[derive(Debug, Deserialize, Validate, ToSchema)]
7894
pub struct CreateApiKeyRequest {
95+
/// API key name (1-100 characters)
7996
#[validate(length(min = 1, max = 100))]
8097
pub name: String,
98+
/// Optional description (max 255 characters)
8199
#[validate(length(max = 255))]
82100
pub description: Option<String>,
101+
/// Optional expiration date
83102
pub expires_at: Option<DateTime<Utc>>,
84103
}
85104

86-
#[derive(Debug, Serialize)]
105+
#[derive(Debug, Serialize, ToSchema)]
87106
pub struct ApiKeyResponse {
88107
pub id: Uuid,
89108
pub name: String,
90109
pub description: Option<String>,
110+
/// The actual API key (only shown once during creation)
91111
pub api_key: String,
92112
pub created_at: DateTime<Utc>,
93113
pub expires_at: Option<DateTime<Utc>>,
94114
pub last_used: Option<DateTime<Utc>>,
95115
}
96116

97-
#[derive(Debug, Serialize)]
117+
#[derive(Debug, Serialize, ToSchema)]
98118
pub struct ApiKeyListItem {
99119
pub id: Uuid,
100120
pub name: String,
@@ -104,13 +124,13 @@ pub struct ApiKeyListItem {
104124
pub last_used: Option<DateTime<Utc>>,
105125
}
106126

107-
#[derive(Debug, Serialize)]
127+
#[derive(Debug, Serialize, ToSchema)]
108128
pub struct ApiKeyListResponse {
109129
pub api_keys: Vec<ApiKeyListItem>,
110130
pub pagination: PaginationInfo,
111131
}
112132

113-
#[derive(Debug, Serialize)]
133+
#[derive(Debug, Serialize, ToSchema)]
114134
pub struct PaginationInfo {
115135
pub page: u32,
116136
pub limit: u32,

src/deployment/models.rs

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@ use serde::{Deserialize, Serialize};
44
use serde_json::Value;
55
use sqlx::FromRow;
66
use std::collections::HashMap;
7+
use utoipa::ToSchema;
78
use uuid::Uuid;
89
use validator::Validate;
910

10-
#[derive(Debug, Clone, FromRow, Serialize, Deserialize)]
11+
#[derive(Debug, Clone, FromRow, Serialize, Deserialize, ToSchema)]
1112
pub struct Deployment {
1213
pub id: Uuid,
1314
pub user_id: Uuid,
@@ -25,49 +26,66 @@ pub struct Deployment {
2526
pub deployed_at: Option<DateTime<Utc>>,
2627
}
2728

28-
#[derive(Debug, Deserialize, Validate)]
29+
#[derive(Debug, Deserialize, Validate, ToSchema)]
2930
pub struct CreateDeploymentRequest {
31+
/// Application name (1-63 characters, DNS-compatible)
3032
#[validate(length(min = 1, max = 63))]
3133
pub app_name: String,
34+
/// Container image URL
3235
#[validate(length(min = 1))]
3336
pub image: String,
37+
/// Port number the container listens on (1-65535)
3438
#[validate(range(min = 1, max = 65535))]
3539
pub port: i32,
40+
/// Environment variables
3641
pub env_vars: Option<HashMap<String, String>>,
42+
/// Number of replicas (1-100)
3743
#[validate(range(min = 1, max = 100))]
3844
pub replicas: Option<i32>,
45+
/// Resource requirements
3946
pub resources: Option<ResourceRequirements>,
47+
/// Health check configuration
4048
pub health_check: Option<HealthCheck>,
49+
/// Registry authentication (if required)
4150
pub registry_auth: Option<RegistryAuth>,
4251
}
4352

44-
#[derive(Debug, Serialize, Deserialize, Validate, Default)]
53+
#[derive(Debug, Serialize, Deserialize, Validate, Default, ToSchema)]
4554
pub struct ResourceRequirements {
55+
/// CPU request/limit (e.g., "100m", "0.5")
4656
pub cpu: Option<String>,
57+
/// Memory request/limit (e.g., "128Mi", "1Gi")
4758
pub memory: Option<String>,
4859
}
4960

50-
#[derive(Debug, Serialize, Deserialize, Validate)]
61+
#[derive(Debug, Serialize, Deserialize, Validate, ToSchema)]
5162
pub struct HealthCheck {
63+
/// Health check endpoint path
5264
#[validate(length(min = 1))]
5365
pub path: String,
66+
/// Initial delay before first health check (0-300 seconds)
5467
#[validate(range(min = 0, max = 300))]
5568
pub initial_delay_seconds: Option<i32>,
69+
/// Interval between health checks (1-300 seconds)
5670
#[validate(range(min = 1, max = 300))]
5771
pub period_seconds: Option<i32>,
72+
/// Timeout for each health check (1-60 seconds)
5873
#[validate(range(min = 1, max = 60))]
5974
pub timeout_seconds: Option<i32>,
75+
/// Number of failures before marking unhealthy (1-10)
6076
#[validate(range(min = 1, max = 10))]
6177
pub failure_threshold: Option<i32>,
6278
}
6379

64-
#[derive(Debug, Deserialize)]
80+
#[derive(Debug, Deserialize, ToSchema)]
6581
pub struct RegistryAuth {
82+
/// Registry username
6683
pub username: String,
84+
/// Registry password
6785
pub password: String,
6886
}
6987

70-
#[derive(Debug, Serialize)]
88+
#[derive(Debug, Serialize, ToSchema)]
7189
pub struct DeploymentResponse {
7290
pub id: Uuid,
7391
pub app_name: String,
@@ -78,7 +96,7 @@ pub struct DeploymentResponse {
7896
pub message: String,
7997
}
8098

81-
#[derive(Debug, Serialize)]
99+
#[derive(Debug, Serialize, ToSchema)]
82100
pub struct DeploymentListItem {
83101
pub id: Uuid,
84102
pub app_name: String,
@@ -90,75 +108,87 @@ pub struct DeploymentListItem {
90108
pub updated_at: DateTime<Utc>,
91109
}
92110

93-
#[derive(Debug, Serialize)]
111+
#[derive(Debug, Serialize, ToSchema)]
94112
pub struct DeploymentListResponse {
95113
pub deployments: Vec<DeploymentListItem>,
96114
pub pagination: PaginationInfo,
97115
}
98116

99-
#[derive(Debug, Serialize)]
117+
#[derive(Debug, Serialize, ToSchema)]
100118
pub struct PaginationInfo {
101119
pub page: u32,
102120
pub limit: u32,
103121
pub total: u64,
104122
pub total_pages: u32,
105123
}
106124

107-
#[derive(Debug, Deserialize, Validate)]
125+
#[derive(Debug, Deserialize, Validate, ToSchema)]
108126
pub struct UpdateDeploymentRequest {
127+
/// New container image
109128
pub image: Option<String>,
129+
/// Updated environment variables
110130
pub env_vars: Option<HashMap<String, String>>,
131+
/// New replica count (1-100)
111132
#[validate(range(min = 1, max = 100))]
112133
pub replicas: Option<i32>,
134+
/// Updated resource requirements
113135
pub resources: Option<ResourceRequirements>,
114136
}
115137

116-
#[derive(Debug, Deserialize, Validate)]
138+
#[derive(Debug, Deserialize, Validate, ToSchema)]
117139
pub struct ScaleDeploymentRequest {
140+
/// Number of replicas (0-100)
118141
#[validate(range(min = 0, max = 100))]
119142
pub replicas: i32,
120143
}
121144

122-
#[derive(Debug, Deserialize)]
145+
#[derive(Debug, Deserialize, ToSchema)]
123146
pub struct LogsQuery {
147+
/// Number of lines to show from the end
124148
pub tail: Option<i32>,
149+
/// Follow log output (streaming)
125150
pub follow: Option<bool>,
151+
/// Show logs after this timestamp
126152
pub since: Option<DateTime<Utc>>,
153+
/// Show logs before this timestamp
127154
pub until: Option<DateTime<Utc>>,
128155
}
129156

130-
#[derive(Debug, Serialize)]
157+
#[derive(Debug, Serialize, ToSchema)]
131158
pub struct LogEntry {
132159
pub timestamp: DateTime<Utc>,
133160
pub level: String,
134161
pub message: String,
135162
pub source: String,
136163
}
137164

138-
#[derive(Debug, Serialize)]
165+
#[derive(Debug, Serialize, ToSchema)]
139166
pub struct LogsResponse {
140167
pub logs: Vec<LogEntry>,
141168
}
142169

143-
#[derive(Debug, Deserialize)]
170+
#[derive(Debug, Deserialize, ToSchema)]
144171
pub struct MetricsQuery {
172+
/// Start time for metrics
145173
pub from: Option<DateTime<Utc>>,
174+
/// End time for metrics
146175
pub to: Option<DateTime<Utc>>,
176+
/// Metrics resolution
147177
pub resolution: Option<String>,
148178
}
149179

150-
#[derive(Debug, Serialize)]
180+
#[derive(Debug, Serialize, ToSchema)]
151181
pub struct MetricPoint {
152182
pub timestamp: DateTime<Utc>,
153183
pub value: f64,
154184
}
155185

156-
#[derive(Debug, Serialize)]
186+
#[derive(Debug, Serialize, ToSchema)]
157187
pub struct MetricsResponse {
158188
pub metrics: HashMap<String, Vec<MetricPoint>>,
159189
}
160190

161-
#[derive(Debug, Serialize)]
191+
#[derive(Debug, Serialize, ToSchema)]
162192
pub struct DeploymentStatus {
163193
pub status: String,
164194
pub health: String,
@@ -168,20 +198,21 @@ pub struct DeploymentStatus {
168198
pub restart_count: i32,
169199
}
170200

171-
#[derive(Debug, Serialize)]
201+
#[derive(Debug, Serialize, ToSchema)]
172202
pub struct ReplicaStatus {
173203
pub desired: i32,
174204
pub ready: i32,
175205
pub available: i32,
176206
}
177207

178-
#[derive(Debug, Deserialize, Validate)]
208+
#[derive(Debug, Deserialize, Validate, ToSchema)]
179209
pub struct AddDomainRequest {
210+
/// Custom domain name (1-253 characters)
180211
#[validate(length(min = 1, max = 253))]
181212
pub domain: String,
182213
}
183214

184-
#[derive(Debug, Serialize)]
215+
#[derive(Debug, Serialize, ToSchema)]
185216
pub struct DomainResponse {
186217
pub id: Uuid,
187218
pub domain: String,
@@ -190,19 +221,19 @@ pub struct DomainResponse {
190221
pub dns_records: Vec<DnsRecord>,
191222
}
192223

193-
#[derive(Debug, Serialize)]
224+
#[derive(Debug, Serialize, ToSchema)]
194225
pub struct DnsRecord {
195226
pub record_type: String,
196227
pub name: String,
197228
pub value: String,
198229
}
199230

200-
#[derive(Debug, Serialize)]
231+
#[derive(Debug, Serialize, ToSchema)]
201232
pub struct DomainListResponse {
202233
pub domains: Vec<DomainListItem>,
203234
}
204235

205-
#[derive(Debug, Serialize)]
236+
#[derive(Debug, Serialize, ToSchema)]
206237
pub struct DomainListItem {
207238
pub id: Uuid,
208239
pub domain: String,

0 commit comments

Comments
 (0)