shared/domain/signing_keys/
repository.rs1use std::sync::Arc;
2
3use chrono::{Duration, Utc};
4
5use crate::error::{CoreError, InternalError, ResourceKind, Result, TokenErrorType};
6
7use super::model::SigningKey;
8use super::ports::database::DatabaseAdapter;
9use super::ports::query::QueryBuilder;
10
11#[derive(Clone)]
12pub struct SigningKeysRepository {
13 adapter: Arc<dyn DatabaseAdapter<SigningKey>>,
14}
15
16impl SigningKeysRepository {
17 pub fn new(adapter: Arc<dyn DatabaseAdapter<SigningKey>>) -> Self {
18 Self { adapter }
19 }
20}
21
22impl SigningKeysRepository {
23 #[tracing::instrument(name = "db.signing_key.insert", skip(self, signing_key))]
24 pub async fn insert(&self, signing_key: SigningKey) -> Result<String> {
25 match self.adapter.insert(signing_key).await {
26 Ok(id) => Ok(id),
27 Err(err) => {
28 tracing::error!("Failed to insert signing_key to database - {err}");
29 Err(CoreError::Internal(InternalError::Database(
30 err.to_string(),
31 )))
32 }
33 }
34 }
35
36 #[tracing::instrument(name = "db.signing_keys.find", skip(self))]
37 pub async fn find(&self) -> Result<SigningKey> {
38 let filter = QueryBuilder::default().eq("status", "active");
39
40 match self.adapter.find_one(filter).await {
41 Ok(Some(key)) => Ok(key),
42 Ok(None) => Err(CoreError::NotFound(ResourceKind::Token {
44 token_type: TokenErrorType::Token,
45 })),
46 Err(err) => {
47 tracing::error!(error_code = "InternalError::Database", error = %err, "Database query failed");
48 Err(err)
49 }
50 }
51 }
52
53 #[tracing::instrument(name = "db.signingkeys.find_valid_keys", skip(self))]
54 pub async fn find_valid_keys(&self) -> Result<Vec<SigningKey>> {
55 let filter = QueryBuilder::default()
56 .ne("status", "revoked")
57 .gt("expiresAt", Utc::now());
58
59 match self.adapter.find_all(filter).await {
60 Ok(permissions) => Ok(permissions),
61 Err(err) => {
62 tracing::error!(error_code = "InternalError::Database", error = %err, "Database query failed");
63 Err(err)
64 }
65 }
66 }
67
68 #[tracing::instrument(name = "db.signingkeys.findall", skip(self))]
69 pub async fn find_all(&self) -> Result<Vec<SigningKey>> {
70 let filter = QueryBuilder::default();
71
72 match self.adapter.find_all(filter).await {
73 Ok(keys) => Ok(keys),
74 Err(err) => {
75 tracing::error!(error_code = "InternalError::Database", error = %err, "Database query failed");
76 Err(err)
77 }
78 }
79 }
80
81 #[tracing::instrument(name = "db.signing_keys.find", skip(self))]
82 pub async fn retire_oldkey(&self, max_token_ttl: i64) -> Result<SigningKey> {
83 let filter = QueryBuilder::default().eq("status", "active");
84 let update = QueryBuilder::default()
85 .set("status", "retired")
86 .set("rotatedAt", Utc::now())
87 .set("expiresAt", Utc::now() + Duration::seconds(max_token_ttl));
88
89 match self.adapter.find_one_and_update(filter, update).await {
90 Ok(Some(key)) => Ok(key),
91 Ok(None) => Err(CoreError::NotFound(ResourceKind::Token {
92 token_type: TokenErrorType::Token,
93 })),
94 Err(err) => {
95 tracing::error!(error_code = "InternalError::Database", error = %err, "Database query failed");
96 Err(err)
97 }
98 }
99 }
100
101 #[tracing::instrument(name = "db.signing_keys.revoke", skip(self))]
102 pub async fn revoke_key(&self, id: &str) -> Result<SigningKey> {
103 let filter = QueryBuilder::default().eq("kid", id);
104 let update = QueryBuilder::default().set("status", "revoked");
105
106 match self.adapter.find_one_and_update(filter, update).await {
107 Ok(Some(key)) => Ok(key),
108 Ok(None) => Err(CoreError::NotFound(ResourceKind::Token {
109 token_type: TokenErrorType::Token,
110 })),
111 Err(err) => {
112 tracing::error!(error_code = "InternalError::Database", error = %err, "Database query failed");
113 Err(err)
114 }
115 }
116 }
117
118 #[tracing::instrument(name = "db.permission.find", skip(self, id))]
119 pub async fn delete(&self, id: &str) -> Result<()> {
120 let filter = QueryBuilder::default().eq("id", id);
121
122 match self.adapter.delete_one(filter).await {
123 Ok(_) => Ok(()),
124 Err(err) => {
125 tracing::error!(error_code = "InternalError::Database", error = %err, "Database query failed");
126 Err(err)
127 }
128 }
129 }
130}