feat(backend): check of no path conflict between flow and flow's primary schedules

This commit is contained in:
Ruben Fiszel
2022-07-20 14:43:08 +02:00
parent 14ec8d190f
commit de160fba45
3 changed files with 99 additions and 2 deletions
+42
View File
@@ -167,6 +167,27 @@
"nullable": []
}
},
"0d6412bc3ebb1d58bdd9cbcef774dacf9016fa402af5c1b4e339b9a3d7163d5e": {
"query": "SELECT EXISTS (SELECT 1 FROM schedule WHERE path = $1 AND workspace_id = $2 AND path != script_path)",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
}
},
"0dd3fe3ddf9cb72760687d2ee0950afdcce2d54721bfe8dba008b15e4b581956": {
"query": "DELETE FROM account WHERE id = $1 AND workspace_id = $2",
"describe": {
@@ -2909,6 +2930,27 @@
]
}
},
"e262f83b672a558092dc959b28a919f18e44b2a0d03b27b0ddba99896940c6d3": {
"query": "SELECT EXISTS (SELECT 1 FROM flow WHERE path = $1 AND workspace_id = $2)",
"describe": {
"columns": [
{
"ordinal": 0,
"name": "exists",
"type_info": "Bool"
}
],
"parameters": {
"Left": [
"Text",
"Text"
]
},
"nullable": [
null
]
}
},
"e3eeda2e19bfbfd5aadd71c40774f7e93c8479a777fdb2828607b1db36361726": {
"query": "INSERT INTO usr_to_group\n VALUES ($1, 'all', $2)",
"describe": {
+27 -2
View File
@@ -16,12 +16,12 @@ use axum::{
};
use serde::{Deserialize, Serialize};
use sql_builder::SqlBuilder;
use sqlx::FromRow;
use sqlx::{FromRow, Postgres, Transaction};
use crate::{
audit::{audit_log, ActionKind},
db::{UserDB, DB},
error::{Error, JsonResult, Result},
error::{self, Error, JsonResult, Result},
jobs::RawCode,
scripts::Schema,
users::Authed,
@@ -171,6 +171,8 @@ async fn create_flow(
// cron::Schedule::from_str(&ns.schedule).map_err(|e| error::Error::BadRequest(e.to_string()))?;
let mut tx = user_db.begin(&authed).await?;
check_schedule_conflict(&mut tx, &w_id, &nf.path).await?;
sqlx::query!(
"INSERT INTO flow (workspace_id, path, summary, description, value, edited_by, edited_at, schema) VALUES ($1, $2, $3, $4, $5, $6, $7, $8::text::json)",
w_id,
@@ -205,6 +207,27 @@ async fn create_flow(
Ok(nf.path.to_string())
}
async fn check_schedule_conflict<'c>(
tx: &mut Transaction<'c, Postgres>,
w_id: &str,
path: &str,
) -> error::Result<()> {
let exists_flow = sqlx::query_scalar!(
"SELECT EXISTS (SELECT 1 FROM schedule WHERE path = $1 AND workspace_id = $2 AND path != script_path)",
path,
w_id
)
.fetch_one(tx)
.await?
.unwrap_or(false);
if exists_flow {
return Err(error::Error::BadConfig(format!(
"A flow cannot have the same path as a schedule if the schedule does not trigger that same flow: {path}",
)));
};
Ok(())
}
async fn update_flow(
authed: Authed,
Extension(user_db): Extension<UserDB>,
@@ -214,6 +237,8 @@ async fn update_flow(
let mut tx = user_db.begin(&authed).await?;
let flow_path = flow_path.to_path();
check_schedule_conflict(&mut tx, &w_id, flow_path).await?;
let schema = nf.schema.map(|x| x.0);
let flow = sqlx::query_scalar!(
"UPDATE flow SET path = $1, summary = $2, description = $3, value = $4, edited_by = $5, edited_at = $6, schema = $7 WHERE path = $8 AND workspace_id = $9 RETURNING path",
+30
View File
@@ -129,6 +129,8 @@ async fn create_schedule(
cron::Schedule::from_str(&ns.schedule).map_err(|e| error::Error::BadRequest(e.to_string()))?;
let mut tx = user_db.begin(&authed).await?;
check_flow_conflict(&mut tx, &w_id, &ns.path, ns.is_flow, &ns.script_path).await?;
let schedule = sqlx::query_as!(Schedule,
"INSERT INTO schedule (workspace_id, path, schedule, offset_, edited_by, script_path, is_flow, args) VALUES ($1, $2, $3, $4, $5, $6, $7, $8) RETURNING *",
w_id,
@@ -167,6 +169,32 @@ async fn create_schedule(
Ok(ns.path.to_string())
}
async fn check_flow_conflict<'c>(
tx: &mut Transaction<'c, Postgres>,
w_id: &str,
path: &str,
is_flow: bool,
script_path: &str,
) -> error::Result<()> {
if path != script_path || !is_flow {
let exists_flow = sqlx::query_scalar!(
"SELECT EXISTS (SELECT 1 FROM flow WHERE path = $1 AND workspace_id = $2)",
path,
w_id
)
.fetch_one(tx)
.await?
.unwrap_or(false);
if exists_flow {
return Err(error::Error::BadConfig(format!(
"If a schedule has the same path as or a flow, it must be its primary schedule and hence can only trigger it.
However the provided path is: {script_path} and is_flow is: {is_flow}",
)));
};
}
Ok(())
}
#[derive(Deserialize)]
pub struct EditSchedule {
pub schedule: String,
@@ -194,6 +222,8 @@ async fn edit_schedule(
let mut tx = user_db.begin(&authed).await?;
check_flow_conflict(&mut tx, &w_id, &path, es.is_flow, &es.script_path).await?;
clear_schedule(&mut tx, path).await?;
let schedule = sqlx::query_as!(Schedule,
"UPDATE schedule SET schedule = $1, script_path = $2, is_flow = $3, args = $4 WHERE path = $5 AND workspace_id = $6 RETURNING *",