mz_sql/session/
user.rs
1use std::collections::{BTreeMap, BTreeSet};
11use std::sync::LazyLock;
12
13use mz_repr::role_id::RoleId;
14use mz_repr::user::{ExternalUserMetadata, InternalUserMetadata};
15use serde::Serialize;
16
17pub const SYSTEM_USER_NAME: &str = "mz_system";
18pub static SYSTEM_USER: LazyLock<User> = LazyLock::new(|| User {
19 name: SYSTEM_USER_NAME.into(),
20 external_metadata: None,
21 internal_metadata: None,
22});
23
24pub const SUPPORT_USER_NAME: &str = "mz_support";
25pub static SUPPORT_USER: LazyLock<User> = LazyLock::new(|| User {
26 name: SUPPORT_USER_NAME.into(),
27 external_metadata: None,
28 internal_metadata: None,
29});
30
31pub const ANALYTICS_USER_NAME: &str = "mz_analytics";
32pub static ANALYTICS_USER: LazyLock<User> = LazyLock::new(|| User {
33 name: ANALYTICS_USER_NAME.into(),
34 external_metadata: None,
35 internal_metadata: None,
36});
37
38pub static INTERNAL_USER_NAMES: LazyLock<BTreeSet<String>> = LazyLock::new(|| {
39 [&SYSTEM_USER, &SUPPORT_USER, &ANALYTICS_USER]
40 .into_iter()
41 .map(|user| user.name.clone())
42 .collect()
43});
44
45pub static INTERNAL_USER_NAME_TO_DEFAULT_CLUSTER: LazyLock<BTreeMap<String, String>> =
46 LazyLock::new(|| {
47 [
48 (&SYSTEM_USER, "mz_system"),
49 (&SUPPORT_USER, "mz_catalog_server"),
50 (&ANALYTICS_USER, "mz_analytics"),
51 ]
52 .into_iter()
53 .map(|(user, cluster)| (user.name.clone(), cluster.to_string()))
54 .collect()
55 });
56
57pub static HTTP_DEFAULT_USER: LazyLock<User> = LazyLock::new(|| User {
58 name: "anonymous_http_user".into(),
59 external_metadata: None,
60 internal_metadata: None,
61});
62
63#[derive(Debug, Clone, Serialize)]
65pub struct User {
66 pub name: String,
68 pub external_metadata: Option<ExternalUserMetadata>,
70 pub internal_metadata: Option<InternalUserMetadata>,
71}
72
73impl From<&User> for mz_pgwire_common::UserMetadata {
74 fn from(user: &User) -> mz_pgwire_common::UserMetadata {
75 mz_pgwire_common::UserMetadata {
76 is_admin: user.is_external_admin(),
77 should_limit_connections: user.limit_max_connections(),
78 }
79 }
80}
81
82impl PartialEq for User {
83 fn eq(&self, other: &User) -> bool {
84 self.name == other.name
85 }
86}
87
88impl User {
89 pub fn is_internal(&self) -> bool {
91 INTERNAL_USER_NAMES.contains(&self.name)
92 }
93
94 pub fn is_external_admin(&self) -> bool {
96 self.external_metadata
97 .as_ref()
98 .map(|metadata| metadata.admin)
99 .clone()
100 .unwrap_or(false)
101 }
102
103 pub fn is_internal_admin(&self) -> bool {
104 self.internal_metadata
105 .as_ref()
106 .map(|metadata| metadata.superuser)
107 .clone()
108 .unwrap_or(false)
109 }
110
111 pub fn is_superuser(&self) -> bool {
113 matches!(self.kind(), UserKind::Superuser)
114 }
115
116 pub fn is_system_user(&self) -> bool {
118 self == &*SYSTEM_USER
119 }
120
121 pub fn limit_max_connections(&self) -> bool {
123 !self.is_internal()
124 }
125
126 pub fn kind(&self) -> UserKind {
128 if self.is_external_admin() || self.is_system_user() || self.is_internal_admin() {
129 UserKind::Superuser
130 } else {
131 UserKind::Regular
132 }
133 }
134}
135
136#[derive(Debug, Copy, Clone)]
137pub enum UserKind {
138 Regular,
139 Superuser,
140}
141
142pub const MZ_SYSTEM_ROLE_ID: RoleId = RoleId::System(1);
143pub const MZ_SUPPORT_ROLE_ID: RoleId = RoleId::System(2);
144pub const MZ_ANALYTICS_ROLE_ID: RoleId = RoleId::System(3);
145pub const MZ_MONITOR_ROLE_ID: RoleId = RoleId::Predefined(1);
146pub const MZ_MONITOR_REDACTED_ROLE_ID: RoleId = RoleId::Predefined(2);
147
148#[derive(Debug, Clone)]
153pub struct RoleMetadata {
154 pub authenticated_role: RoleId,
156 pub session_role: RoleId,
160 pub current_role: RoleId,
163}
164
165impl RoleMetadata {
166 pub fn new(id: RoleId) -> RoleMetadata {
168 RoleMetadata {
169 authenticated_role: id,
170 session_role: id,
171 current_role: id,
172 }
173 }
174}