93 lines
2.4 KiB
Rust
93 lines
2.4 KiB
Rust
/*
|
|
* SPDX-FileCopyrightText: 2020 Stalwart Labs LLC <[email protected]>
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*/
|
|
|
|
use rusqlite::{Connection, params};
|
|
|
|
pub fn unique_role(
|
|
conn: &Connection,
|
|
role: Option<&str>,
|
|
exclude_id: Option<i64>,
|
|
) -> rusqlite::Result<Option<String>> {
|
|
let Some(r) = role else {
|
|
return Ok(None);
|
|
};
|
|
let taken: bool = conn.query_row(
|
|
"SELECT EXISTS(SELECT 1 FROM mailboxes WHERE role = ?1 AND (?2 IS NULL OR id != ?2))",
|
|
params![r, exclude_id],
|
|
|row| row.get(0),
|
|
)?;
|
|
Ok((!taken).then(|| r.to_owned()))
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
use crate::db::init;
|
|
|
|
fn mem() -> Connection {
|
|
let conn = Connection::open_in_memory().unwrap();
|
|
init::apply_schema(&conn).unwrap();
|
|
conn
|
|
}
|
|
|
|
fn insert(conn: &Connection, name: &str, role: Option<&str>) -> i64 {
|
|
conn.execute(
|
|
"INSERT INTO mailboxes (name, parent_id, role, sort_order, is_subscribed)
|
|
VALUES (?1, NULL, ?2, 0, 1)",
|
|
params![name, role],
|
|
)
|
|
.unwrap();
|
|
conn.last_insert_rowid()
|
|
}
|
|
|
|
#[test]
|
|
fn first_claimant_keeps_role_second_is_dropped() {
|
|
let conn = mem();
|
|
let first = unique_role(&conn, Some("sent"), None).unwrap();
|
|
assert_eq!(first.as_deref(), Some("sent"));
|
|
insert(&conn, "Sent", first.as_deref());
|
|
|
|
let second = unique_role(&conn, Some("sent"), None).unwrap();
|
|
assert_eq!(second, None);
|
|
}
|
|
|
|
#[test]
|
|
fn null_role_stays_null() {
|
|
let conn = mem();
|
|
assert_eq!(unique_role(&conn, None, None).unwrap(), None);
|
|
}
|
|
|
|
#[test]
|
|
fn distinct_roles_are_independent() {
|
|
let conn = mem();
|
|
insert(&conn, "Sent", Some("sent"));
|
|
assert_eq!(
|
|
unique_role(&conn, Some("trash"), None).unwrap().as_deref(),
|
|
Some("trash")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn update_excludes_own_row() {
|
|
let conn = mem();
|
|
let id = insert(&conn, "Sent", Some("sent"));
|
|
assert_eq!(
|
|
unique_role(&conn, Some("sent"), Some(id))
|
|
.unwrap()
|
|
.as_deref(),
|
|
Some("sent")
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn update_detects_other_holder() {
|
|
let conn = mem();
|
|
insert(&conn, "Sent", Some("sent"));
|
|
let other = insert(&conn, "Envoyés", None);
|
|
assert_eq!(unique_role(&conn, Some("sent"), Some(other)).unwrap(), None);
|
|
}
|
|
}
|