Skip to main content

drizzle_core/traits/
policy.rs

1use core::any::Any;
2
3use crate::{SQLParam, SQLSchemaType, SQLTable, TableRef, ToSQL};
4
5/// A PostgreSQL row-level security policy's metadata as associated
6/// constants, generated by `#[PostgresPolicy]`.
7///
8/// Every `DrizzlePolicy` also implements [`SQLPolicyInfo`].
9pub trait DrizzlePolicy: Send + Sync + 'static {
10    /// Policy name.
11    const POLICY_NAME: &'static str;
12
13    /// AS clause (`PERMISSIVE` or `RESTRICTIVE`).
14    const AS_CLAUSE: Option<&'static str> = None;
15
16    /// FOR clause (`ALL`, `SELECT`, `INSERT`, `UPDATE`, or `DELETE`).
17    const FOR_CLAUSE: Option<&'static str> = None;
18
19    /// Roles in the `TO` clause.
20    const TO: &'static [&'static str] = &[];
21
22    /// `USING` expression, as SQL text.
23    const USING: Option<&'static str> = None;
24
25    /// `WITH CHECK` expression, as SQL text.
26    const WITH_CHECK: Option<&'static str> = None;
27
28    /// The table this policy belongs to.
29    fn table_ref() -> &'static TableRef;
30}
31
32// Every `DrizzlePolicy` is a `SQLPolicyInfo`.
33impl<T: DrizzlePolicy> SQLPolicyInfo for T {
34    fn table(&self) -> &'static TableRef {
35        T::table_ref()
36    }
37
38    fn name(&self) -> &'static str {
39        T::POLICY_NAME
40    }
41
42    fn as_clause(&self) -> Option<&'static str> {
43        T::AS_CLAUSE
44    }
45
46    fn for_clause(&self) -> Option<&'static str> {
47        T::FOR_CLAUSE
48    }
49
50    fn to(&self) -> &'static [&'static str] {
51        T::TO
52    }
53
54    fn using(&self) -> Option<&'static str> {
55        T::USING
56    }
57
58    fn with_check(&self) -> Option<&'static str> {
59        T::WITH_CHECK
60    }
61}
62
63/// Runtime metadata of a policy, usable as a trait object. See
64/// [`DrizzlePolicy`] for what each field means.
65pub trait SQLPolicyInfo: Any + Send + Sync {
66    /// The table the policy applies to.
67    fn table(&self) -> &'static TableRef;
68    /// The policy name.
69    fn name(&self) -> &'static str;
70    /// `PERMISSIVE` or `RESTRICTIVE`, if set.
71    fn as_clause(&self) -> Option<&'static str>;
72    /// The command the policy covers, if set.
73    fn for_clause(&self) -> Option<&'static str>;
74    /// Roles in the `TO` clause.
75    fn to(&self) -> &'static [&'static str];
76    /// `USING` expression, as SQL text.
77    fn using(&self) -> Option<&'static str>;
78    /// `WITH CHECK` expression, as SQL text.
79    fn with_check(&self) -> Option<&'static str>;
80}
81
82impl core::fmt::Debug for dyn SQLPolicyInfo {
83    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
84        f.debug_struct("SQLPolicyInfo")
85            .field("name", &self.name())
86            .field("table", &self.table().name)
87            .field("as_clause", &self.as_clause())
88            .field("for_clause", &self.for_clause())
89            .field("to", &self.to())
90            .finish()
91    }
92}
93
94/// A PostgreSQL row-level security policy. Renders as its `CREATE POLICY`
95/// statement.
96#[diagnostic::on_unimplemented(
97    message = "`{Self}` is not a SQL policy for this dialect",
98    label = "ensure this type was derived with #[PostgresPolicy]"
99)]
100pub trait SQLPolicy<'a, Type: SQLSchemaType, Value: SQLParam + 'a>:
101    SQLPolicyInfo + ToSQL<'a, Value>
102{
103    /// The table the policy applies to.
104    type Table: SQLTable<'a, Type, Value>;
105}