coven_storage/
credentials.rs1use coven_crypto::SecretBytes;
2use coven_crypto::SecretText;
3use coven_format::code_fields::{FieldReader, FieldWriter};
4use serde::{Deserialize, Serialize};
5
6#[derive(Clone, Serialize, Deserialize)]
8#[serde(deny_unknown_fields)]
9pub struct S3Credentials {
10 pub access_key_id: String,
12 pub secret_access_key: SecretText,
14}
15
16impl S3Credentials {
17 pub fn encode(&self) -> Result<SecretBytes, crate::StorageError> {
19 self.validate()?;
20 crate::secret_json::encode(self)
21 }
22
23 pub fn decode(bytes: &[u8]) -> Result<Self, crate::StorageError> {
25 let keys: Self = crate::secret_json::decode(bytes)?;
26 keys.validate()?;
27 Ok(keys)
28 }
29
30 pub(crate) fn pack(&self, out: &mut FieldWriter) -> Result<(), coven_format::Error> {
33 out.text(&self.access_key_id)?;
34 out.text(self.secret_access_key.as_str())
35 }
36
37 pub(crate) fn unpack(input: &mut FieldReader<'_>) -> Result<Self, crate::StorageError> {
39 let keys = Self {
40 access_key_id: input.text("access key id")?,
41 secret_access_key: input.secret_text("secret access key")?,
42 };
43 keys.validate()?;
44 Ok(keys)
45 }
46
47 pub fn validate(&self) -> Result<(), crate::StorageError> {
49 if self.access_key_id.is_empty() || self.secret_access_key.as_str().is_empty() {
50 return Err(crate::StorageFailure::InvalidConfiguration
51 .with_source("S3 requires an access key id and secret"));
52 }
53 Ok(())
54 }
55}
56
57#[derive(Clone, Serialize, Deserialize)]
59#[serde(deny_unknown_fields)]
60pub struct OAuthTokens {
61 pub client_id: String,
63 pub access: crate::OAuthAccess,
65 pub access_token: SecretText,
67 pub refresh_token: Option<SecretText>,
70}
71
72#[derive(Clone, Serialize, Deserialize)]
74pub enum StorageCredentials {
75 S3(S3Credentials),
77 OAuth(OAuthTokens),
79 CloudKit,
81}
82
83impl StorageCredentials {
84 pub fn encode(&self) -> Result<SecretBytes, crate::StorageError> {
86 crate::secret_json::encode(self)
87 }
88 pub fn decode(bytes: &[u8]) -> Result<Self, crate::StorageError> {
90 crate::secret_json::decode(bytes)
91 }
92}
93
94#[cfg(test)]
95#[path = "credentials_tests.rs"]
96mod tests;