Skip to main content

systemprompt_security/authz/types/
kinds.rs

1//! Rule and entity kind tags with parse/display.
2//!
3//! Copyright (c) systemprompt.io — Business Source License 1.1.
4//! See <https://systemprompt.io> for licensing details.
5
6use std::fmt;
7use std::str::FromStr;
8
9use serde::{Deserialize, Serialize};
10
11use crate::authz::error::AuthzError;
12
13#[derive(
14    Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, sqlx::Type,
15)]
16#[sqlx(type_name = "TEXT", rename_all = "lowercase")]
17#[serde(rename_all = "lowercase")]
18pub enum RuleType {
19    User,
20    Role,
21}
22
23impl fmt::Display for RuleType {
24    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
25        f.write_str(match *self {
26            Self::User => "user",
27            Self::Role => "role",
28        })
29    }
30}
31
32impl FromStr for RuleType {
33    type Err = AuthzError;
34
35    fn from_str(s: &str) -> Result<Self, Self::Err> {
36        match s {
37            "user" => Ok(Self::User),
38            "role" => Ok(Self::Role),
39            other => Err(AuthzError::InvalidRuleType(other.to_owned())),
40        }
41    }
42}
43
44#[derive(
45    Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, sqlx::Type,
46)]
47#[sqlx(type_name = "TEXT", rename_all = "lowercase")]
48#[serde(rename_all = "lowercase")]
49pub enum Access {
50    Allow,
51    Deny,
52}
53
54impl fmt::Display for Access {
55    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
56        f.write_str(match *self {
57            Self::Allow => "allow",
58            Self::Deny => "deny",
59        })
60    }
61}
62
63impl FromStr for Access {
64    type Err = AuthzError;
65
66    fn from_str(s: &str) -> Result<Self, Self::Err> {
67        match s {
68            "allow" => Ok(Self::Allow),
69            "deny" => Ok(Self::Deny),
70            other => Err(AuthzError::InvalidAccess(other.to_owned())),
71        }
72    }
73}
74
75#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
76#[serde(rename_all = "snake_case")]
77pub enum EntityKind {
78    GatewayRoute,
79    McpServer,
80    Plugin,
81    Agent,
82    Marketplace,
83    Skill,
84    Hook,
85    SlackWorkspace,
86    SlackChannel,
87    TeamsTenant,
88    TeamsConversation,
89}
90
91impl EntityKind {
92    pub const fn as_str(self) -> &'static str {
93        match self {
94            Self::GatewayRoute => "gateway_route",
95            Self::McpServer => "mcp_server",
96            Self::Plugin => "plugin",
97            Self::Agent => "agent",
98            Self::Marketplace => "marketplace",
99            Self::Skill => "skill",
100            Self::Hook => "hook",
101            Self::SlackWorkspace => "slack_workspace",
102            Self::SlackChannel => "slack_channel",
103            Self::TeamsTenant => "teams_tenant",
104            Self::TeamsConversation => "teams_conversation",
105        }
106    }
107}
108
109impl FromStr for EntityKind {
110    type Err = AuthzError;
111
112    fn from_str(s: &str) -> Result<Self, Self::Err> {
113        match s {
114            "gateway_route" => Ok(Self::GatewayRoute),
115            "mcp_server" => Ok(Self::McpServer),
116            "plugin" => Ok(Self::Plugin),
117            "agent" => Ok(Self::Agent),
118            "marketplace" => Ok(Self::Marketplace),
119            "skill" => Ok(Self::Skill),
120            "hook" => Ok(Self::Hook),
121            "slack_workspace" => Ok(Self::SlackWorkspace),
122            "slack_channel" => Ok(Self::SlackChannel),
123            "teams_tenant" => Ok(Self::TeamsTenant),
124            "teams_conversation" => Ok(Self::TeamsConversation),
125            other => Err(AuthzError::Validation(format!(
126                "unknown entity_type: {other}"
127            ))),
128        }
129    }
130}
131
132impl fmt::Display for EntityKind {
133    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
134        f.write_str(self.as_str())
135    }
136}