reifydb_auth/service/
token.rs1use std::collections::HashMap;
5
6use reifydb_catalog::{drop_expired_tokens, drop_token, drop_tokens_by_identity, find_token_by_value};
7use reifydb_core::interface::{
8 auth::AuthStep,
9 catalog::token::{Token, TokenId},
10};
11use reifydb_transaction::transaction::Transaction;
12use reifydb_value::{
13 error::Error,
14 value::{datetime::DateTime, identity::IdentityId},
15};
16
17use super::AuthService;
18
19impl AuthService {
20 pub fn validate_token(&self, token: &str) -> Result<Option<Token>, Error> {
21 let mut txn = self.engine.begin_query()?;
22
23 if let Some(def) = find_token_by_value(&mut Transaction::Query(&mut txn), token)? {
24 if let Some(expires_at) = def.expires_at
25 && expires_at < self.now()?
26 {
27 return Ok(None);
28 }
29
30 let catalog = self.engine.catalog();
31 let enabled = catalog
32 .find_identity(&mut Transaction::Query(&mut txn), def.identity)?
33 .is_some_and(|identity| identity.enabled);
34 if !enabled {
35 return Ok(None);
36 }
37
38 return Ok(Some(def));
39 }
40
41 self.validate_catalog_token(token)
42 }
43
44 fn validate_catalog_token(&self, token: &str) -> Result<Option<Token>, Error> {
45 let Some(provider) = self.auth_registry.get("token") else {
46 return Ok(None);
47 };
48
49 let mut txn = self.engine.begin_query()?;
50 let catalog = self.engine.catalog();
51
52 let auths = catalog.list_authentications_by_method(&mut Transaction::Query(&mut txn), "token")?;
53
54 let creds = HashMap::from([("token".to_string(), token.to_string())]);
55
56 for auth in auths {
57 if let Ok(AuthStep::Authenticated) = provider.authenticate(&auth.properties, &creds)
58 && let Some(ident) =
59 catalog.find_identity(&mut Transaction::Query(&mut txn), auth.identity)?
60 && ident.enabled
61 {
62 return Ok(Some(Token {
63 id: 0,
64 token: token.to_string(),
65 identity: ident.id,
66 expires_at: None,
67 created_at: DateTime::default(),
68 }));
69 }
70 }
71
72 Ok(None)
73 }
74
75 pub fn revoke_token(&self, token: &str) -> Result<bool, Error> {
76 let Some(def) = self.find_token(token)? else {
77 return Ok(false);
78 };
79 self.drop_and_commit(def.id)?;
80 Ok(true)
81 }
82
83 #[inline]
84 fn find_token(&self, token: &str) -> Result<Option<Token>, Error> {
85 let mut txn = self.engine.begin_query()?;
86 find_token_by_value(&mut Transaction::Query(&mut txn), token)
87 }
88
89 #[inline]
90 fn drop_and_commit(&self, id: TokenId) -> Result<(), Error> {
91 let mut admin = self.engine.begin_admin()?;
92 drop_token(&mut admin, id)?;
93 admin.commit()?;
94 Ok(())
95 }
96
97 pub fn revoke_all(&self, identity: IdentityId) -> Result<(), Error> {
98 let mut admin = self.engine.begin_admin()?;
99 drop_tokens_by_identity(&mut admin, identity)?;
100 admin.commit()?;
101 Ok(())
102 }
103
104 pub fn cleanup_expired(&self) -> Result<(), Error> {
105 self.challenges.cleanup_expired();
106
107 let mut admin = self.engine.begin_admin()?;
108 drop_expired_tokens(&mut admin, self.now()?)?;
109 admin.commit()?;
110 Ok(())
111 }
112}