#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AuthAction {
CreateIndex,
CreateTable,
CreateTempIndex,
CreateTempTable,
CreateTempTrigger,
CreateTempView,
CreateTrigger,
CreateView,
Delete,
Insert,
Select,
Update,
Read,
DropIndex,
DropTable,
DropTempIndex,
DropTempTable,
DropTempTrigger,
DropTempView,
DropTrigger,
DropView,
Pragma,
Transaction,
Attach,
Detach,
AlterTable,
Reindex,
Analyze,
CreateVtable,
DropVtable,
Function,
Savepoint,
Recursive,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum AuthResult {
Ok,
Deny,
Ignore,
}
pub trait Authorizer: Send + Sync {
fn authorize(
&self,
action: AuthAction,
arg1: Option<&str>,
arg2: Option<&str>,
db_name: Option<&str>,
trigger: Option<&str>,
) -> AuthResult;
}
pub type AuthorizerAction = AuthAction;
pub type AuthorizerDecision = AuthResult;
#[cfg(test)]
mod tests {
use super::*;
struct ReadOnlyAuthorizer;
impl Authorizer for ReadOnlyAuthorizer {
fn authorize(
&self,
action: AuthAction,
_arg1: Option<&str>,
_arg2: Option<&str>,
_db_name: Option<&str>,
_trigger: Option<&str>,
) -> AuthResult {
match action {
AuthAction::Read | AuthAction::Select => AuthResult::Ok,
_ => AuthResult::Deny,
}
}
}
#[test]
fn test_authorizer_allow_select() {
let auth = ReadOnlyAuthorizer;
assert_eq!(
auth.authorize(AuthAction::Select, None, None, Some("main"), None),
AuthResult::Ok
);
}
#[test]
fn test_authorizer_deny_insert() {
let auth = ReadOnlyAuthorizer;
assert_eq!(
auth.authorize(AuthAction::Insert, Some("users"), None, Some("main"), None),
AuthResult::Deny
);
}
#[test]
fn test_authorizer_ignore_read() {
struct ColumnHider;
impl Authorizer for ColumnHider {
fn authorize(
&self,
action: AuthAction,
_arg1: Option<&str>,
arg2: Option<&str>,
_db_name: Option<&str>,
_trigger: Option<&str>,
) -> AuthResult {
if action == AuthAction::Read && arg2 == Some("secret") {
return AuthResult::Ignore;
}
AuthResult::Ok
}
}
let auth = ColumnHider;
assert_eq!(
auth.authorize(
AuthAction::Read,
Some("users"),
Some("secret"),
Some("main"),
None
),
AuthResult::Ignore
);
assert_eq!(
auth.authorize(
AuthAction::Read,
Some("users"),
Some("name"),
Some("main"),
None
),
AuthResult::Ok
);
}
#[test]
fn test_authorizer_trigger_context() {
struct TriggerAwareAuthorizer;
impl Authorizer for TriggerAwareAuthorizer {
fn authorize(
&self,
_action: AuthAction,
_arg1: Option<&str>,
_arg2: Option<&str>,
_db_name: Option<&str>,
trigger: Option<&str>,
) -> AuthResult {
if trigger.is_some() {
return AuthResult::Deny;
}
AuthResult::Ok
}
}
let auth = TriggerAwareAuthorizer;
assert_eq!(
auth.authorize(AuthAction::Insert, Some("t"), None, Some("main"), None),
AuthResult::Ok
);
assert_eq!(
auth.authorize(
AuthAction::Insert,
Some("t"),
None,
Some("main"),
Some("trg_audit")
),
AuthResult::Deny
);
}
#[test]
#[allow(clippy::too_many_lines)]
fn test_auth_action_all_variants() {
let actions = [
AuthAction::CreateIndex,
AuthAction::CreateTable,
AuthAction::CreateTempIndex,
AuthAction::CreateTempTable,
AuthAction::CreateTempTrigger,
AuthAction::CreateTempView,
AuthAction::CreateTrigger,
AuthAction::CreateView,
AuthAction::Delete,
AuthAction::Insert,
AuthAction::Select,
AuthAction::Update,
AuthAction::Read,
AuthAction::DropIndex,
AuthAction::DropTable,
AuthAction::DropTempIndex,
AuthAction::DropTempTable,
AuthAction::DropTempTrigger,
AuthAction::DropTempView,
AuthAction::DropTrigger,
AuthAction::DropView,
AuthAction::Pragma,
AuthAction::Transaction,
AuthAction::Attach,
AuthAction::Detach,
AuthAction::AlterTable,
AuthAction::Reindex,
AuthAction::Analyze,
AuthAction::CreateVtable,
AuthAction::DropVtable,
AuthAction::Function,
AuthAction::Savepoint,
AuthAction::Recursive,
];
assert_eq!(actions.len(), 33);
for a in &actions {
let _ = match a {
AuthAction::CreateIndex
| AuthAction::CreateTable
| AuthAction::CreateTempIndex
| AuthAction::CreateTempTable
| AuthAction::CreateTempTrigger
| AuthAction::CreateTempView
| AuthAction::CreateTrigger
| AuthAction::CreateView
| AuthAction::Delete
| AuthAction::Insert
| AuthAction::Select
| AuthAction::Update
| AuthAction::Read
| AuthAction::DropIndex
| AuthAction::DropTable
| AuthAction::DropTempIndex
| AuthAction::DropTempTable
| AuthAction::DropTempTrigger
| AuthAction::DropTempView
| AuthAction::DropTrigger
| AuthAction::DropView
| AuthAction::Pragma
| AuthAction::Transaction
| AuthAction::Attach
| AuthAction::Detach
| AuthAction::AlterTable
| AuthAction::Reindex
| AuthAction::Analyze
| AuthAction::CreateVtable
| AuthAction::DropVtable
| AuthAction::Function
| AuthAction::Savepoint
| AuthAction::Recursive => true,
};
}
}
#[test]
fn test_authorizer_send_sync() {
fn assert_send_sync<T: Send + Sync>() {}
assert_send_sync::<ReadOnlyAuthorizer>();
}
}