-
Notifications
You must be signed in to change notification settings - Fork 2.8k
refactor: clean up client side code for creating schedule #6805
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
Changes from all commits
c283ff8
0a3073e
ec55327
d9acf31
768ec8f
9716875
42b23f3
5433159
1f93883
8fb0fe1
8dd57a0
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,5 @@ | ||
| use std::sync::Arc; | ||
| use tokio::fs; | ||
|
|
||
| use axum::{ | ||
| extract::{Path, Query, State}, | ||
|
|
@@ -9,13 +10,30 @@ use axum::{ | |
| use serde::{Deserialize, Serialize}; | ||
|
|
||
| use crate::routes::errors::ErrorResponse; | ||
| use crate::routes::recipe_utils::validate_recipe; | ||
| use crate::state::AppState; | ||
| use goose::scheduler::ScheduledJob; | ||
| use goose::recipe::Recipe; | ||
| use goose::scheduler::{get_default_scheduled_recipes_dir, ScheduledJob}; | ||
|
|
||
| fn validate_schedule_id(id: &str) -> Result<(), ErrorResponse> { | ||
| let is_valid = !id.is_empty() | ||
| && id | ||
| .chars() | ||
| .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_' || c == ' '); | ||
|
|
||
| if !is_valid { | ||
| return Err(ErrorResponse::bad_request( | ||
| "Schedule name must use only alphanumeric characters, hyphens, underscores, or spaces" | ||
| .to_string(), | ||
| )); | ||
| } | ||
| Ok(()) | ||
| } | ||
|
|
||
| #[derive(Deserialize, Serialize, utoipa::ToSchema)] | ||
| pub struct CreateScheduleRequest { | ||
| id: String, | ||
| recipe_source: String, | ||
| recipe: Recipe, | ||
| cron: String, | ||
| } | ||
|
|
||
|
|
@@ -89,20 +107,47 @@ async fn create_schedule( | |
| State(state): State<Arc<AppState>>, | ||
| Json(req): Json<CreateScheduleRequest>, | ||
| ) -> Result<Json<ScheduledJob>, ErrorResponse> { | ||
| let scheduler = state.scheduler(); | ||
| let id = req.id.trim().to_string(); | ||
| validate_schedule_id(&id)?; | ||
|
|
||
| if req.recipe.check_for_security_warnings() { | ||
| return Err(ErrorResponse::bad_request( | ||
| "This recipe contains hidden characters that could be malicious. Please remove them before trying to save.".to_string(), | ||
| )); | ||
| } | ||
| if let Err(err) = validate_recipe(&req.recipe) { | ||
| return Err(ErrorResponse { | ||
| message: err.message, | ||
| status: err.status, | ||
| }); | ||
| } | ||
| let scheduled_recipes_dir = get_default_scheduled_recipes_dir().map_err(|e| { | ||
| ErrorResponse::internal(format!("Failed to get scheduled recipes directory: {}", e)) | ||
| })?; | ||
|
|
||
| let recipe_path = scheduled_recipes_dir.join(format!("{}.yaml", id)); | ||
| let yaml_content = req | ||
| .recipe | ||
| .to_yaml() | ||
| .map_err(|e| ErrorResponse::internal(format!("Failed to convert recipe to YAML: {}", e)))?; | ||
| fs::write(&recipe_path, yaml_content) | ||
| .await | ||
| .map_err(|e| ErrorResponse::internal(format!("Failed to save recipe file: {}", e)))?; | ||
|
Comment on lines
+133
to
+135
|
||
|
|
||
| let job = ScheduledJob { | ||
| id: req.id, | ||
| source: req.recipe_source, | ||
| id, | ||
| source: recipe_path.to_string_lossy().into_owned(), | ||
| cron: req.cron, | ||
| last_run: None, | ||
| currently_running: false, | ||
| paused: false, | ||
| current_session_id: None, | ||
| process_start_time: None, | ||
| }; | ||
|
|
||
| let scheduler = state.scheduler(); | ||
| scheduler | ||
| .add_scheduled_job(job.clone(), true) | ||
| .add_scheduled_job(job.clone(), false) | ||
| .await | ||
|
Comment on lines
+124
to
151
|
||
| .map_err(|e| match e { | ||
| goose::scheduler::SchedulerError::CronParseError(msg) => { | ||
|
|
@@ -117,6 +162,7 @@ async fn create_schedule( | |
| }, | ||
| _ => ErrorResponse::internal(format!("Error creating schedule: {}", e)), | ||
| })?; | ||
|
|
||
| Ok(Json(job)) | ||
| } | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
validate_schedule_idallows leading/trailing spaces, which can create hard-to-reference schedule IDs (and awkward filenames like "foo .yaml"); consider trimmingidbefore validation and/or rejecting IDs that start/end with whitespace.