1use super::super::db::queries as db;
14use rocket::http::Status;
15use rocket::serde::json::{json, Json, Value};
16use rocket::{delete, get, http::ContentType, post, put, Data, State};
17use serde::{Deserialize, Serialize};
18use std::sync::Arc;
19
20use crate::DatabaseManager;
22
23use libomni::types::db::v1 as types;
24use types::app::{App, AppWithInstances};
25
26#[derive(Debug, Serialize, Deserialize, Clone)]
30pub struct Application {
31 id: String,
33 name: String,
35 owner: String,
37 instances: i64,
39 memory: i64,
41 status: String,
43 created_at: chrono::DateTime<chrono::Utc>,
45 updated_at: chrono::DateTime<chrono::Utc>,
47}
48
49#[derive(Debug, Serialize, Deserialize)]
51pub struct ScaleRequest {
52 instances: i32,
54 memory: i32,
56}
57
58#[derive(Debug, Serialize, Deserialize)]
60pub struct AppStats {
61 cpu_usage: f64,
63 memory_usage: i64,
65 disk_usage: i64,
67 requests_per_second: f64,
69 response_time_ms: i64,
71}
72
73#[derive(Debug, Serialize, Deserialize)]
75pub struct CreateAppRequest {
76 name: String,
78 memory: i64,
80 instances: i64,
82 org_id: i64,
84}
85
86#[derive(Debug, Serialize, Deserialize)]
88pub struct UpdateAppRequest {
89 name: String,
91 memory: i64,
93 instances: i64,
95 org_id: i64,
97}
98
99#[get("/platform/<platform_id>/apps?<page>&<per_page>")]
112pub async fn list_apps(
113 platform_id: i64,
114 page: Option<i64>,
115 per_page: Option<i64>,
116 db_manager: &State<Arc<DatabaseManager>>,
117) -> Result<Json<Value>, (Status, Json<Value>)> {
118 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
120 Ok(platform) => platform,
121 Err(_) => {
122 return Err((
123 Status::NotFound,
124 Json(json!({
125 "error": "Platform not found",
126 "message": format!("Platform with ID {} does not exist", platform_id)
127 }))
128 ));
129 }
130 };
131
132 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
134 Ok(pool) => pool,
135 Err(_) => {
136 return Err((
137 Status::InternalServerError,
138 Json(json!({
139 "error": "Database error",
140 "message": "Failed to connect to platform database"
141 }))
142 ));
143 }
144 };
145
146 match (page, per_page) {
147 (Some(p), Some(pp)) => {
148 let apps = match db::app::list_apps(&pool, p, pp).await {
149 Ok(apps) => apps,
150 Err(_) => {
151 return Err((
152 Status::InternalServerError,
153 Json(json!({
154 "error": "Database error",
155 "message": "Failed to retrieve applications"
156 }))
157 ));
158 }
159 };
160
161 let total_count = match db::app::count_apps(&pool).await {
162 Ok(count) => count,
163 Err(_) => {
164 return Err((
165 Status::InternalServerError,
166 Json(json!({
167 "error": "Database error",
168 "message": "Failed to count applications"
169 }))
170 ));
171 }
172 };
173
174 let total_pages = (total_count / pp);
175
176 let response = json!({
177 "apps": apps,
178 "pagination": {
179 "page": p,
180 "per_page": pp,
181 "total_count": total_count,
182 "total_pages": total_pages
183 }
184 });
185
186 Ok(Json(response))
187 }
188 _ => Err((
189 Status::BadRequest,
190 Json(json!({
191 "error": "Missing pagination parameters",
192 "message": "Please provide both 'page' and 'per_page' parameters"
193 }))
194 ))
195 }
196}
197
198#[get("/platform/<platform_id>/app_with_instances/<app_id>")]
200pub async fn get_app_with_instances(
201 db_manager: &State<Arc<DatabaseManager>>,
202 platform_id: i64,
203 app_id: i64
204) -> Result<Json<AppWithInstances>, (Status, Json<Value>)> {
205 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
207 Ok(platform) => platform,
208 Err(_) => {
209 return Err((
210 Status::NotFound,
211 Json(json!({
212 "error": "Platform not found",
213 "message": format!("Platform with ID {} does not exist", platform_id)
214 }))
215 ));
216 }
217 };
218
219 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
221 Ok(pool) => pool,
222 Err(_) => {
223 return Err((
224 Status::InternalServerError,
225 Json(json!({
226 "error": "Database error",
227 "message": "Failed to connect to platform database"
228 }))
229 ));
230 }
231 };
232
233 match db::app::get_app_with_instances(&pool, app_id).await {
234 Ok(app_with_instances) => {
235 Ok(Json(app_with_instances))
236 }
237 Err(_) => Err((
238 Status::InternalServerError,
239 Json(json!({
240 "error": "Failed to fetch app with instances",
241 "message": "An error occurred while retrieving the application data"
242 })),
243 )),
244 }
245}
246
247#[get("/platform/<platform_id>/app-count")]
249pub async fn count_apps(
250 platform_id: i64,
251 db_manager: &State<Arc<DatabaseManager>>
252) -> Result<Json<i64>, (Status, Json<Value>)> {
253 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
255 Ok(platform) => platform,
256 Err(_) => {
257 return Err((
258 Status::NotFound,
259 Json(json!({
260 "error": "Platform not found",
261 "message": format!("Platform with ID {} does not exist", platform_id)
262 }))
263 ));
264 }
265 };
266
267 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
269 Ok(pool) => pool,
270 Err(_) => {
271 return Err((
272 Status::InternalServerError,
273 Json(json!({
274 "error": "Database error",
275 "message": "Failed to connect to platform database"
276 }))
277 ));
278 }
279 };
280
281 match db::app::count_apps(&pool).await {
282 Ok(count) => Ok(Json(count)),
283 Err(_) => Err((
284 Status::InternalServerError,
285 Json(json!({
286 "error": "Database error",
287 "message": "Failed to count applications"
288 }))
289 )),
290 }
291}
292
293#[get("/platform/<platform_id>/apps/<app_id>")]
305pub async fn get_app(
306 platform_id: i64,
307 app_id: i64,
308 db_manager: &State<Arc<DatabaseManager>>
309) -> Result<Json<App>, (Status, Json<Value>)> {
310 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
312 Ok(platform) => platform,
313 Err(_) => {
314 return Err((
315 Status::NotFound,
316 Json(json!({
317 "error": "Platform not found",
318 "message": format!("Platform with ID {} does not exist", platform_id)
319 }))
320 ));
321 }
322 };
323
324 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
326 Ok(pool) => pool,
327 Err(_) => {
328 return Err((
329 Status::InternalServerError,
330 Json(json!({
331 "error": "Database error",
332 "message": "Failed to connect to platform database"
333 }))
334 ));
335 }
336 };
337
338 match db::app::get_app_by_id(&pool, app_id).await {
339 Ok(app) => Ok(Json(app)),
340 Err(_) => {
341 Err((
342 Status::NotFound,
343 Json(json!({
344 "error": "App not found",
345 "message": format!("App with ID {} could not be found", app_id)
346 }))
347 ))
348 }
349 }
350}
351
352#[post("/platform/<platform_id>/apps", format = "json", data = "<app_request>")]
364pub async fn create_app(
365 platform_id: i64,
366 app_request: Json<CreateAppRequest>,
367 db_manager: &State<Arc<DatabaseManager>>,
368) -> Result<Json<App>, (Status, Json<Value>)> {
369 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
371 Ok(platform) => platform,
372 Err(_) => {
373 return Err((
374 Status::NotFound,
375 Json(json!({
376 "error": "Platform not found",
377 "message": format!("Platform with ID {} does not exist", platform_id)
378 }))
379 ));
380 }
381 };
382
383 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
385 Ok(pool) => pool,
386 Err(_) => {
387 return Err((
388 Status::InternalServerError,
389 Json(json!({
390 "error": "Database error",
391 "message": "Failed to connect to platform database"
392 }))
393 ));
394 }
395 };
396
397 match db::app::create_app(
398 &pool,
399 &app_request.name,
400 app_request.org_id,
401 None,
402 None,
403 None,
404 None,
405 ).await {
406 Ok(app) => Ok(Json(app)),
407 Err(_) => {
408 Err((
409 Status::InternalServerError,
410 Json(json!({
411 "error": "Database error",
412 "message": "Failed to create application"
413 }))
414 ))
415 }
416 }
417}
418
419#[post("/platform/<platform_id>/apps/<app_id>", format = "json", data = "<app_request>")]
432pub async fn update_app(
433 platform_id: i64,
434 app_request: Json<UpdateAppRequest>,
435 db_manager: &State<Arc<DatabaseManager>>,
436 app_id: i64,
437) -> Result<Json<App>, (Status, Json<Value>)> {
438 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
440 Ok(platform) => platform,
441 Err(_) => {
442 return Err((
443 Status::NotFound,
444 Json(json!({
445 "error": "Platform not found",
446 "message": format!("Platform with ID {} does not exist", platform_id)
447 }))
448 ));
449 }
450 };
451
452 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
454 Ok(pool) => pool,
455 Err(_) => {
456 return Err((
457 Status::InternalServerError,
458 Json(json!({
459 "error": "Database error",
460 "message": "Failed to connect to platform database"
461 }))
462 ));
463 }
464 };
465
466 match db::app::update_app(
467 &pool,
468 app_id,
469 Some(&app_request.name),
470 None,
471 None,
472 None,
473 None,
474 None,
475 ).await {
476 Ok(app) => Ok(Json(app)),
477 Err(_) => {
478 Err((
479 Status::InternalServerError,
480 Json(json!({
481 "error": "Database error",
482 "message": "Failed to update application"
483 }))
484 ))
485 }
486 }
487}
488
489#[get("/platform/<platform_id>/apps/<app_id>/stats")]
501pub async fn get_app_stats(
502 platform_id: i64,
503 app_id: String,
504 db_manager: &State<Arc<DatabaseManager>>
505) -> Result<Json<AppStats>, (Status, Json<Value>)> {
506 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
508 Ok(platform) => platform,
509 Err(_) => {
510 return Err((
511 Status::NotFound,
512 Json(json!({
513 "error": "Platform not found",
514 "message": format!("Platform with ID {} does not exist", platform_id)
515 }))
516 ));
517 }
518 };
519
520 let _pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
522 Ok(pool) => pool,
523 Err(_) => {
524 return Err((
525 Status::InternalServerError,
526 Json(json!({
527 "error": "Database error",
528 "message": "Failed to connect to platform database"
529 }))
530 ));
531 }
532 };
533
534 let app_stats = AppStats {
536 cpu_usage: 0.0,
537 memory_usage: 0,
538 disk_usage: 0,
539 requests_per_second: 0.0,
540 response_time_ms: 0,
541 };
542 Ok(Json(app_stats))
543}
544
545#[put("/platform/<platform_id>/apps/<app_id>/start")]
557pub async fn start_app(
558 platform_id: i64,
559 app_id: String,
560 db_manager: &State<Arc<DatabaseManager>>
561) -> Result<Json<Application>, (Status, Json<Value>)> {
562 todo!()
565}
566
567#[put("/platform/<platform_id>/apps/<app_id>/stop")]
579pub async fn stop_app(
580 platform_id: i64,
581 app_id: String,
582 db_manager: &State<Arc<DatabaseManager>>
583) -> Result<Json<Application>, (Status, Json<Value>)> {
584 todo!()
587}
588
589#[put("/platform/<platform_id>/apps/<app_id>/scale", format = "json", data = "<scale>")]
602pub async fn scale_app(
603 platform_id: i64,
604 app_id: String,
605 scale: Json<ScaleRequest>,
606 db_manager: &State<Arc<DatabaseManager>>
607) -> Result<Json<Application>, (Status, Json<Value>)> {
608 todo!()
611}
612
613#[delete("/platform/<platform_id>/apps/<app_id>")]
625pub async fn delete_app(
626 platform_id: i64,
627 app_id: String,
628 db_manager: &State<Arc<DatabaseManager>>,
629) -> Result<Json<Value>, (Status, Json<Value>)> {
630 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
632 Ok(platform) => platform,
633 Err(_) => {
634 return Err((
635 Status::NotFound,
636 Json(json!({
637 "error": "Platform not found",
638 "message": format!("Platform with ID {} does not exist", platform_id)
639 }))
640 ));
641 }
642 };
643
644 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
646 Ok(pool) => pool,
647 Err(_) => {
648 return Err((
649 Status::InternalServerError,
650 Json(json!({
651 "error": "Database error",
652 "message": "Failed to connect to platform database"
653 }))
654 ));
655 }
656 };
657
658 match app_id.parse::<i64>() {
659 Ok(id) => {
660 match db::app::delete_app(&pool, id).await {
661 Ok(_) => Ok(Json(json!({ "status": "deleted" }))),
662 Err(_) => {
663 Err((
664 Status::InternalServerError,
665 Json(json!({
666 "error": "Database error",
667 "message": "Failed to delete application"
668 }))
669 ))
670 }
671 }
672 }
673 Err(e) => {
674 Err((
675 Status::BadRequest,
676 Json(json!({
677 "error": "Invalid ID format",
678 "message": format!("The application ID must be a valid integer: {}", e)
679 }))
680 ))
681 }
682 }
683}
684
685#[post(
712 "/platform/<platform_id>/apps/<app_id>/releases/<release_version>/upload",
713 format = "multipart/form-data",
714 data = "<data>"
715)]
716pub async fn release(
717 platform_id: i64,
718 app_id: String,
719 release_version: String,
720 content_type: &ContentType,
721 data: Data<'_>,
722 db_manager: &State<Arc<DatabaseManager>>,
723) -> Result<Status, Status> {
724 match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
729 Ok(_) => {
730 super::helpers::release::release(app_id, release_version, content_type, data).await
732 },
733 Err(_) => {
734 Err(Status::NotFound)
736 }
737 }
738}
739
740#[get("/platform/<platform_id>/apps/<app_id>/instances?<page>&<per_page>")]
742pub async fn list_instances(
743 platform_id: i64,
744 app_id: i64,
745 page: Option<i64>,
746 per_page: Option<i64>,
747 db_manager: &State<Arc<DatabaseManager>>,
748) -> Result<Json<Value>, (Status, Json<Value>)> {
749 let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
751 Ok(platform) => platform,
752 Err(_) => {
753 return Err((
754 Status::NotFound,
755 Json(json!({
756 "error": "Platform not found",
757 "message": format!("Platform with ID {} does not exist", platform_id)
758 }))
759 ));
760 }
761 };
762
763 let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
765 Ok(pool) => pool,
766 Err(_) => {
767 return Err((
768 Status::InternalServerError,
769 Json(json!({
770 "error": "Database error",
771 "message": "Failed to connect to platform database"
772 }))
773 ));
774 }
775 };
776
777 match (page, per_page) {
778 (Some(p), Some(pp)) => {
779 let instances = match db::app::list_instances(&pool, app_id, p, pp).await {
780 Ok(instances) => instances,
781 Err(_) => {
782 return Err((
783 Status::InternalServerError,
784 Json(json!({
785 "error": "Database error",
786 "message": "Failed to retrieve instances"
787 }))
788 ));
789 }
790 };
791
792 let total_count = match db::app::count_instances_by_app(&pool, app_id).await {
793 Ok(count) => count,
794 Err(_) => {
795 return Err((
796 Status::InternalServerError,
797 Json(json!({
798 "error": "Database error",
799 "message": "Failed to count instances"
800 }))
801 ));
802 }
803 };
804
805 let total_pages = (total_count as f64 / pp as f64).ceil() as i64;
806
807 let response = json!({
808 "instances": instances,
809 "pagination": {
810 "page": p,
811 "per_page": pp,
812 "total_count": total_count,
813 "total_pages": total_pages
814 }
815 });
816
817 Ok(Json(response))
818 }
819 _ => Err((
820 Status::BadRequest,
821 Json(json!({
822 "error": "Missing pagination parameters",
823 "message": "Please provide both 'page' and 'per_page' parameters"
824 }))
825 ))
826 }
827}