mybatis/
intercept.rs

1use mybatis_core::convert::StmtConvert;
2
3use crate::mybatis::Mybatis;
4use crate::plus::MybatisPlus;
5use mybatis_core::db::DriverType;
6use mybatis_core::Error;
7use mybatis_sql::TEMPLATE;
8use rbson::Bson;
9use std::fmt::{Debug, Display};
10
11/// sql intercept
12pub trait SqlIntercept: Send + Sync + Debug {
13    ///the name
14    fn name(&self) -> &str {
15        std::any::type_name::<Self>()
16    }
17    /// do intercept sql/args
18    /// is_prepared_sql: if is run in prepared_sql=ture
19    fn do_intercept(
20        &self,
21        rb: &Mybatis,
22        sql: &mut String,
23        args: &mut Vec<rbson::Bson>,
24        is_prepared_sql: bool,
25    ) -> Result<(), Error>;
26}
27
28#[derive(Debug)]
29pub struct MyBatisLogFormatSqlIntercept {}
30
31impl SqlIntercept for MyBatisLogFormatSqlIntercept {
32    fn do_intercept(
33        &self,
34        rb: &Mybatis,
35        sql: &mut String,
36        args: &mut Vec<Bson>,
37        is_prepared_sql: bool,
38    ) -> Result<(), Error> {
39        let driver_type = rb.driver_type()?;
40        match driver_type {
41            DriverType::None => {}
42            DriverType::Mysql | DriverType::Postgres | DriverType::Sqlite | DriverType::Mssql => {
43                let mut formated = format!("[format_sql]{}", sql);
44                for index in 0..args.len() {
45                    let mut data = String::new();
46                    driver_type.stmt_convert(index, &mut data);
47                    formated =
48                        formated.replacen(&data, &format!("{}", args.get(index).unwrap()), 1);
49                }
50                rb.log_plugin.info(0, &formated);
51            }
52        }
53        return Ok(());
54    }
55}
56
57/// Prevent full table updates and deletions
58#[derive(Debug)]
59pub struct BlockAttackDeleteInterceptor {}
60
61impl SqlIntercept for BlockAttackDeleteInterceptor {
62    fn do_intercept(
63        &self,
64        rb: &Mybatis,
65        sql: &mut String,
66        args: &mut Vec<Bson>,
67        is_prepared_sql: bool,
68    ) -> Result<(), Error> {
69        let sql = sql.trim();
70        if sql.starts_with(TEMPLATE.delete_from.value)
71            && !sql.contains(TEMPLATE.r#where.left_right_space)
72        {
73            return Err(Error::from(format!(
74                "[mybatis][BlockAttackDeleteInterceptor] not allow attack sql:{}",
75                sql
76            )));
77        }
78        return Ok(());
79    }
80}
81
82/// Prevent full table updates and deletions
83#[derive(Debug)]
84pub struct BlockAttackUpdateInterceptor {}
85
86impl SqlIntercept for BlockAttackUpdateInterceptor {
87    fn do_intercept(
88        &self,
89        rb: &Mybatis,
90        sql: &mut String,
91        args: &mut Vec<Bson>,
92        is_prepared_sql: bool,
93    ) -> Result<(), Error> {
94        let sql = sql.trim();
95        if sql.starts_with(TEMPLATE.update.value)
96            && !sql.contains(TEMPLATE.r#where.left_right_space)
97        {
98            return Err(Error::from(format!(
99                "[mybatis][BlockAttackUpdateInterceptor] not allow attack sql:{}",
100                sql
101            )));
102        }
103        return Ok(());
104    }
105}