sea_query/audit/
mod.rs

1mod common;
2mod delete;
3mod insert;
4mod select;
5mod update;
6
7use crate::{DynIden, TableName};
8
9pub trait AuditTrait {
10    fn audit(&self) -> Result<QueryAccessAudit, Error>;
11
12    /// Shorthand for `audit().unwrap()`
13    fn audit_unwrap(&self) -> QueryAccessAudit {
14        self.audit().unwrap()
15    }
16}
17
18#[derive(Debug)]
19#[non_exhaustive]
20pub struct QueryAccessAudit {
21    pub requests: Vec<QueryAccessRequest>,
22}
23
24#[derive(Debug)]
25#[non_exhaustive]
26pub struct QueryAccessRequest {
27    pub access_type: AccessType,
28    /// The table name can be qualified as `(database.)(schema.)table`.
29    pub schema_table: TableName,
30}
31
32#[derive(Debug, Copy, Clone, PartialEq, Eq)]
33pub enum AccessType {
34    Select,
35    Insert,
36    Update,
37    Delete,
38    Schema(SchemaOper),
39}
40
41/// Schema Operation
42#[derive(Debug, Copy, Clone, PartialEq, Eq)]
43pub enum SchemaOper {
44    Create,
45    Alter,
46    Drop,
47    Rename,
48    Truncate,
49}
50
51impl AccessType {
52    pub fn as_str(&self) -> &'static str {
53        match self {
54            AccessType::Select => "select",
55            AccessType::Insert => "insert",
56            AccessType::Update => "update",
57            AccessType::Delete => "delete",
58            AccessType::Schema(SchemaOper::Create) => "schema_create",
59            AccessType::Schema(SchemaOper::Alter) => "schema_alter",
60            AccessType::Schema(SchemaOper::Drop) => "schema_drop",
61            AccessType::Schema(SchemaOper::Rename) => "schema_rename",
62            AccessType::Schema(SchemaOper::Truncate) => "schema_truncate",
63        }
64    }
65}
66
67impl QueryAccessAudit {
68    /// This filters the selects from access requests.
69    pub fn selects(&self) -> Vec<TableName> {
70        self.requests
71            .iter()
72            .filter_map(|item| {
73                if item.access_type == AccessType::Select {
74                    Some(item.schema_table.clone())
75                } else {
76                    None
77                }
78            })
79            .collect()
80    }
81
82    /// Warning: this discards the schema part of TableName.
83    /// Intended for testing only.
84    pub fn selected_tables(&self) -> Vec<DynIden> {
85        self.filter_table_with_access_type(AccessType::Select)
86    }
87
88    /// Warning: this discards the schema part of TableName.
89    /// Intended for testing only.
90    pub fn inserted_tables(&self) -> Vec<DynIden> {
91        self.filter_table_with_access_type(AccessType::Insert)
92    }
93
94    /// Warning: this discards the schema part of TableName.
95    /// Intended for testing only.
96    pub fn updated_tables(&self) -> Vec<DynIden> {
97        self.filter_table_with_access_type(AccessType::Update)
98    }
99
100    /// Warning: this discards the schema part of TableName.
101    /// Intended for testing only.
102    pub fn deleted_tables(&self) -> Vec<DynIden> {
103        self.filter_table_with_access_type(AccessType::Delete)
104    }
105
106    fn filter_table_with_access_type(&self, access_type: AccessType) -> Vec<DynIden> {
107        self.requests
108            .iter()
109            .filter_map(|item| {
110                if item.access_type == access_type {
111                    Some(item.schema_table.1.clone())
112                } else {
113                    None
114                }
115            })
116            .collect()
117    }
118}
119
120#[derive(Debug, PartialEq, Eq)]
121pub enum Error {
122    /// Unable to parse query
123    UnableToParseQuery,
124    /// Unsupported query
125    UnsupportedQuery,
126}
127
128impl std::error::Error for Error {}
129
130impl std::fmt::Display for Error {
131    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
132        match self {
133            Self::UnableToParseQuery => f.write_str("Unable to parse query"),
134            Self::UnsupportedQuery => f.write_str("Unsupported query"),
135        }
136    }
137}