mod droit;
mod groupe;
mod user;
use crate::admin::helper::resource_entry::ResourceEntry;
pub(crate) fn is_unique_violation(err: &sea_orm::DbErr) -> bool {
#[cfg(any(feature = "postgres", feature = "mysql", feature = "sqlite"))]
{
use sea_orm::{RuntimeErr, sqlx};
if let sea_orm::DbErr::Exec(RuntimeErr::SqlxError(arc_err))
| sea_orm::DbErr::Query(RuntimeErr::SqlxError(arc_err)) = err
&& let sqlx::Error::Database(db_err) = arc_err.as_ref()
{
return db_err.is_unique_violation();
}
}
let s = err.to_string().to_lowercase();
s.contains("23505")
|| s.contains("duplicate key")
|| s.contains("duplicate entry")
|| s.contains("unique constraint")
|| s.contains("duplicated")
}
pub fn builtin_resources() -> Vec<ResourceEntry> {
vec![
user::user_entry(),
droit::droit_entry(),
groupe::groupe_entry(),
]
}
#[cfg(test)]
mod unique_violation_tests {
use super::is_unique_violation;
use sea_orm::DbErr;
#[test]
fn each_engine_wording_is_a_unique_violation() {
for msg in [
"SQLSTATE 23505",
"duplicate key value violates unique constraint \"users_email_key\"",
"UNIQUE constraint failed: users.email (unique constraint)",
"Duplicate entry: duplicated value",
] {
assert!(is_unique_violation(&DbErr::Custom(msg.into())), "{msg}");
}
assert!(!is_unique_violation(&DbErr::Custom(
"connection reset".into()
)));
}
#[test]
fn each_wording_counts_on_its_own() {
for msg in [
"SQLSTATE 23505",
"duplicate key value",
"Duplicate entry 'a@b.c' for key 'email'",
"UNIQUE constraint failed: users.email",
"value duplicated",
] {
assert!(is_unique_violation(&DbErr::Custom(msg.into())), "{msg}");
}
}
#[cfg(feature = "sqlite")]
#[tokio::test]
async fn a_real_not_null_error_is_not_a_unique_violation() {
use sea_orm::{ConnectionTrait, Database};
let db = Database::connect("sqlite::memory:").await.unwrap();
db.execute_unprepared("CREATE TABLE t (v TEXT NOT NULL UNIQUE)")
.await
.unwrap();
let not_null = db
.execute_unprepared("INSERT INTO t (v) VALUES (NULL)")
.await
.unwrap_err();
assert!(!is_unique_violation(¬_null), "{not_null}");
db.execute_unprepared("INSERT INTO t (v) VALUES ('a')")
.await
.unwrap();
let dup = db
.execute_unprepared("INSERT INTO t (v) VALUES ('a')")
.await
.unwrap_err();
assert!(is_unique_violation(&dup), "{dup}");
}
}