rovenue/sessions/
account_token.rs1use std::sync::Arc;
2
3use uuid::Uuid;
4
5use crate::cache::CacheStore;
6use crate::error::{RovenueError, RovenueResult};
7
8pub struct AccountTokenStore {
9 store: Arc<CacheStore>,
10}
11
12impl AccountTokenStore {
13 pub fn new(store: Arc<CacheStore>) -> Self {
14 Self { store }
15 }
16
17 pub fn get_or_create(&self, scope: &str) -> RovenueResult<String> {
21 if scope.trim().is_empty() {
22 return Err(RovenueError::Internal());
23 }
24 if let Some(existing) = self.store.get_app_account_token(scope)? {
25 return Ok(existing);
26 }
27 let new_token = Uuid::new_v4().to_string();
28 self.store.put_app_account_token(scope, &new_token)?;
29 self.store
31 .get_app_account_token(scope)?
32 .ok_or(RovenueError::Storage())
33 }
34
35 pub fn clear(&self) -> RovenueResult<()> {
38 self.store.clear_app_account_tokens()
39 }
40}
41
42#[cfg(test)]
43mod tests {
44 use super::*;
45
46 #[test]
47 fn returns_same_token_on_repeat_calls() {
48 let store = Arc::new(CacheStore::open_in_memory().unwrap());
49 let svc = AccountTokenStore::new(Arc::clone(&store));
50 let t1 = svc.get_or_create("user-a").unwrap();
51 let t2 = svc.get_or_create("user-a").unwrap();
52 assert_eq!(t1, t2);
53 }
54
55 #[test]
56 fn different_scopes_get_different_tokens() {
57 let store = Arc::new(CacheStore::open_in_memory().unwrap());
58 let svc = AccountTokenStore::new(Arc::clone(&store));
59 assert_ne!(
60 svc.get_or_create("user-a").unwrap(),
61 svc.get_or_create("user-b").unwrap(),
62 );
63 }
64
65 #[test]
66 fn token_is_valid_uuid_v4() {
67 let store = Arc::new(CacheStore::open_in_memory().unwrap());
68 let svc = AccountTokenStore::new(Arc::clone(&store));
69 let t = svc.get_or_create("user-a").unwrap();
70 let parsed = Uuid::parse_str(&t).expect("valid UUID");
71 assert_eq!(parsed.get_version_num(), 4);
72 }
73
74 #[test]
75 fn clear_removes_all_tokens() {
76 let store = Arc::new(CacheStore::open_in_memory().unwrap());
77 let svc = AccountTokenStore::new(Arc::clone(&store));
78 svc.get_or_create("user-a").unwrap();
79 svc.get_or_create("user-b").unwrap();
80 assert_eq!(store.count_app_account_tokens().unwrap(), 2);
81 svc.clear().unwrap();
82 assert_eq!(store.count_app_account_tokens().unwrap(), 0);
83 }
84
85 #[test]
86 fn empty_scope_returns_internal_error() {
87 let store = Arc::new(CacheStore::open_in_memory().unwrap());
88 let svc = AccountTokenStore::new(Arc::clone(&store));
89 assert!(svc.get_or_create("").is_err());
90 }
91}