1use std::fmt;
2
3use secrecy::{ExposeSecret, SecretString};
4use serde::{Deserialize, Serialize};
5use zeroize::{Zeroize, ZeroizeOnDrop};
6
7use super::redaction::redact;
8
9#[derive(Debug, Serialize, Zeroize, ZeroizeOnDrop)]
10pub struct DatabaseConfigRequest {
11 pub plugin_name: String,
12 #[serde(serialize_with = "super::serde_secret::serialize")]
13 pub connection_url: SecretString,
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub allowed_roles: Option<Vec<String>>,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 pub username: Option<String>,
18 #[serde(
19 serialize_with = "super::serde_secret::serialize_option",
20 skip_serializing_if = "Option::is_none"
21 )]
22 pub password: Option<SecretString>,
23 #[serde(skip_serializing_if = "Option::is_none")]
24 pub max_open_connections: Option<u32>,
25 #[serde(skip_serializing_if = "Option::is_none")]
26 pub max_idle_connections: Option<u32>,
27 #[serde(skip_serializing_if = "Option::is_none")]
28 pub max_connection_lifetime: Option<String>,
29 #[serde(skip_serializing_if = "Option::is_none")]
30 pub username_template: Option<String>,
31 #[serde(skip_serializing_if = "Option::is_none")]
32 pub verify_connection: Option<bool>,
33}
34
35impl Clone for DatabaseConfigRequest {
36 fn clone(&self) -> Self {
37 Self {
38 plugin_name: self.plugin_name.clone(),
39 connection_url: self.connection_url.clone(),
40 allowed_roles: self.allowed_roles.clone(),
41 username: self.username.clone(),
42 password: self.password.clone(),
43 max_open_connections: self.max_open_connections,
44 max_idle_connections: self.max_idle_connections,
45 max_connection_lifetime: self.max_connection_lifetime.clone(),
46 username_template: self.username_template.clone(),
47 verify_connection: self.verify_connection,
48 }
49 }
50}
51
52#[derive(Debug, Deserialize, Clone)]
53#[non_exhaustive]
54pub struct DatabaseConfig {
55 pub plugin_name: String,
56 pub connection_details: serde_json::Value,
57 #[serde(default)]
58 pub allowed_roles: Vec<String>,
59}
60
61#[derive(Debug, Serialize, Default, Clone)]
62pub struct DatabaseRoleRequest {
63 pub db_name: String,
64 #[serde(skip_serializing_if = "Option::is_none")]
65 pub creation_statements: Option<Vec<String>>,
66 #[serde(skip_serializing_if = "Option::is_none")]
67 pub revocation_statements: Option<Vec<String>>,
68 #[serde(skip_serializing_if = "Option::is_none")]
69 pub rollback_statements: Option<Vec<String>>,
70 #[serde(skip_serializing_if = "Option::is_none")]
71 pub renew_statements: Option<Vec<String>>,
72 #[serde(skip_serializing_if = "Option::is_none")]
73 pub default_ttl: Option<String>,
74 #[serde(skip_serializing_if = "Option::is_none")]
75 pub max_ttl: Option<String>,
76}
77
78#[derive(Debug, Deserialize, Clone)]
79#[non_exhaustive]
80pub struct DatabaseRole {
81 pub db_name: String,
82 #[serde(default)]
83 pub creation_statements: Vec<String>,
84 #[serde(default)]
85 pub revocation_statements: Vec<String>,
86 #[serde(default)]
87 pub rollback_statements: Vec<String>,
88 #[serde(default)]
89 pub renew_statements: Vec<String>,
90 pub default_ttl: u64,
91 pub max_ttl: u64,
92}
93
94#[derive(Debug, Serialize, Default, Clone)]
95pub struct DatabaseStaticRoleRequest {
96 pub db_name: String,
97 pub username: String,
98 #[serde(skip_serializing_if = "Option::is_none")]
99 pub rotation_statements: Option<Vec<String>>,
100 #[serde(skip_serializing_if = "Option::is_none")]
101 pub rotation_period: Option<String>,
102}
103
104#[derive(Debug, Deserialize, Clone)]
105#[non_exhaustive]
106pub struct DatabaseStaticRole {
107 pub db_name: String,
108 pub username: String,
109 #[serde(default)]
110 pub rotation_statements: Vec<String>,
111 pub rotation_period: u64,
112 pub last_vault_rotation: Option<String>,
113}
114
115#[derive(Deserialize, Zeroize, ZeroizeOnDrop)]
116#[non_exhaustive]
117pub struct DatabaseCredentials {
118 pub username: SecretString,
119 pub password: SecretString,
120}
121
122impl Clone for DatabaseCredentials {
123 fn clone(&self) -> Self {
124 Self {
125 username: self.username.clone(),
126 password: self.password.clone(),
127 }
128 }
129}
130
131impl From<(SecretString, SecretString)> for DatabaseCredentials {
132 fn from((username, password): (SecretString, SecretString)) -> Self {
133 Self { username, password }
134 }
135}
136
137impl From<(&str, &str)> for DatabaseCredentials {
138 fn from((username, password): (&str, &str)) -> Self {
139 Self {
140 username: SecretString::from(username.to_owned()),
141 password: SecretString::from(password.to_owned()),
142 }
143 }
144}
145
146impl fmt::Debug for DatabaseCredentials {
147 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
148 f.debug_struct("DatabaseCredentials")
149 .field("username", &redact(self.username.expose_secret()))
150 .field("password", &redact(self.password.expose_secret()))
151 .finish()
152 }
153}
154
155#[derive(Deserialize, Zeroize, ZeroizeOnDrop)]
156#[non_exhaustive]
157pub struct DatabaseStaticCredentials {
158 pub username: SecretString,
159 pub password: SecretString,
160 pub last_vault_rotation: Option<String>,
161 pub rotation_period: u64,
162 pub ttl: u64,
163}
164
165impl Clone for DatabaseStaticCredentials {
166 fn clone(&self) -> Self {
167 Self {
168 username: self.username.clone(),
169 password: self.password.clone(),
170 last_vault_rotation: self.last_vault_rotation.clone(),
171 rotation_period: self.rotation_period,
172 ttl: self.ttl,
173 }
174 }
175}
176
177impl fmt::Debug for DatabaseStaticCredentials {
178 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179 f.debug_struct("DatabaseStaticCredentials")
180 .field("username", &redact(self.username.expose_secret()))
181 .field("password", &redact(self.password.expose_secret()))
182 .field("ttl", &self.ttl)
183 .finish()
184 }
185}