use crate::alloc_prelude::*;
#[cfg(feature = "serde")]
use crate::serde_helpers::cow_from_string;
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "SCREAMING_SNAKE_CASE"))]
pub enum PrivilegeType {
#[default]
All,
Select,
Insert,
Update,
Delete,
Truncate,
References,
Trigger,
}
impl PrivilegeType {
#[must_use]
pub const fn as_sql(&self) -> &'static str {
match self {
Self::All => "ALL",
Self::Select => "SELECT",
Self::Insert => "INSERT",
Self::Update => "UPDATE",
Self::Delete => "DELETE",
Self::Truncate => "TRUNCATE",
Self::References => "REFERENCES",
Self::Trigger => "TRIGGER",
}
}
#[must_use]
pub fn from_sql(s: &str) -> Option<Self> {
match s.to_uppercase().as_str() {
"ALL" => Some(Self::All),
"SELECT" => Some(Self::Select),
"INSERT" => Some(Self::Insert),
"UPDATE" => Some(Self::Update),
"DELETE" => Some(Self::Delete),
"TRUNCATE" => Some(Self::Truncate),
"REFERENCES" => Some(Self::References),
"TRIGGER" => Some(Self::Trigger),
_ => None,
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct PrivilegeDef {
pub grantor: &'static str,
pub grantee: &'static str,
pub schema: &'static str,
pub table: &'static str,
pub privilege_type: PrivilegeType,
pub is_grantable: bool,
}
impl PrivilegeDef {
#[must_use]
pub const fn new(
schema: &'static str,
table: &'static str,
grantee: &'static str,
privilege_type: PrivilegeType,
) -> Self {
Self {
grantor: "",
grantee,
schema,
table,
privilege_type,
is_grantable: false,
}
}
#[must_use]
pub const fn grantor(self, grantor: &'static str) -> Self {
Self { grantor, ..self }
}
#[must_use]
pub const fn grantable(self) -> Self {
Self {
is_grantable: true,
..self
}
}
#[must_use]
pub const fn into_privilege(self) -> Privilege {
Privilege {
grantor: Cow::Borrowed(self.grantor),
grantee: Cow::Borrowed(self.grantee),
schema: Cow::Borrowed(self.schema),
table: Cow::Borrowed(self.table),
privilege_type: self.privilege_type,
is_grantable: self.is_grantable,
}
}
}
impl Default for PrivilegeDef {
fn default() -> Self {
Self::new("public", "", "", PrivilegeType::All)
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "serde", serde(rename_all = "camelCase"))]
pub struct Privilege {
#[cfg_attr(feature = "serde", serde(deserialize_with = "cow_from_string"))]
pub grantor: Cow<'static, str>,
#[cfg_attr(feature = "serde", serde(deserialize_with = "cow_from_string"))]
pub grantee: Cow<'static, str>,
#[cfg_attr(feature = "serde", serde(deserialize_with = "cow_from_string"))]
pub schema: Cow<'static, str>,
#[cfg_attr(feature = "serde", serde(deserialize_with = "cow_from_string"))]
pub table: Cow<'static, str>,
#[cfg_attr(feature = "serde", serde(rename = "type"))]
pub privilege_type: PrivilegeType,
#[cfg_attr(feature = "serde", serde(default))]
pub is_grantable: bool,
}
impl Privilege {
#[must_use]
pub fn new(
schema: impl Into<Cow<'static, str>>,
table: impl Into<Cow<'static, str>>,
grantee: impl Into<Cow<'static, str>>,
privilege_type: PrivilegeType,
) -> Self {
Self {
grantor: Cow::Borrowed(""),
grantee: grantee.into(),
schema: schema.into(),
table: table.into(),
privilege_type,
is_grantable: false,
}
}
#[inline]
#[must_use]
pub fn schema(&self) -> &str {
&self.schema
}
#[inline]
#[must_use]
pub fn table(&self) -> &str {
&self.table
}
#[inline]
#[must_use]
pub fn grantee(&self) -> &str {
&self.grantee
}
#[inline]
#[must_use]
pub fn grantor(&self) -> &str {
&self.grantor
}
}
impl Default for Privilege {
fn default() -> Self {
Self::new("public", "", "", PrivilegeType::All)
}
}
impl From<PrivilegeDef> for Privilege {
fn from(def: PrivilegeDef) -> Self {
def.into_privilege()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_const_privilege_def() {
const PRIV: PrivilegeDef =
PrivilegeDef::new("public", "users", "app_user", PrivilegeType::Select)
.grantor("admin")
.grantable();
assert_eq!(PRIV.schema, "public");
assert_eq!(PRIV.table, "users");
assert_eq!(PRIV.grantee, "app_user");
assert_eq!(PRIV.grantor, "admin");
assert_eq!(PRIV.privilege_type, PrivilegeType::Select);
const {
assert!(PRIV.is_grantable);
}
}
#[test]
fn test_privilege_def_to_privilege() {
const DEF: PrivilegeDef =
PrivilegeDef::new("public", "users", "reader", PrivilegeType::Select);
let priv_ = DEF.into_privilege();
assert_eq!(priv_.schema(), "public");
assert_eq!(priv_.table(), "users");
assert_eq!(priv_.grantee(), "reader");
}
#[test]
fn test_privilege_type_sql() {
assert_eq!(PrivilegeType::Select.as_sql(), "SELECT");
assert_eq!(PrivilegeType::All.as_sql(), "ALL");
assert_eq!(PrivilegeType::Truncate.as_sql(), "TRUNCATE");
}
}