game_manager_lib/utils/oauth/
token_store.rs1use crate::database::core::{delete_secret, get_secret, set_secret};
9use crate::errors::AppError;
10use crate::utils::oauth::config::{refresh_access_token, OAuthProviderConfig, OAuthToken};
11use tauri::AppHandle;
12
13fn secret_key_for(provider_id: &str) -> String {
15 format!("oauth_{provider_id}")
16}
17
18pub fn save_oauth_token(
20 app: &AppHandle,
21 provider_id: &str,
22 token: &OAuthToken,
23) -> Result<(), AppError> {
24 let json = serde_json::to_string(token)?;
25 set_secret(app, &secret_key_for(provider_id), &json)
26}
27
28pub fn load_oauth_token(
34 app: &AppHandle,
35 provider_id: &str,
36) -> Result<Option<OAuthToken>, AppError> {
37 let raw = get_secret(app, &secret_key_for(provider_id))?;
38
39 if raw.is_empty() {
40 return Ok(None);
41 }
42
43 let token: OAuthToken = serde_json::from_str(&raw)?;
44 Ok(Some(token))
45}
46
47pub fn delete_oauth_token(app: &AppHandle, provider_id: &str) -> Result<(), AppError> {
49 delete_secret(app, &secret_key_for(provider_id))
50}
51
52pub async fn get_valid_access_token(
59 app: &AppHandle,
60 config: &OAuthProviderConfig,
61) -> Result<String, AppError> {
62 let stored = load_oauth_token(app, config.provider_id)?
63 .ok_or_else(|| AppError::OAuthTokenNotFound(config.provider_id.to_string()))?;
64
65 if !stored.is_expired() {
66 return Ok(stored.access_token);
67 }
68
69 let refresh_token = stored.refresh_token.as_ref().ok_or_else(|| {
70 AppError::OAuthTokenNotFound(format!(
71 "{}: token expirado e sem refresh_token, é necessário novo login",
72 config.provider_id
73 ))
74 })?;
75
76 let refreshed = refresh_access_token(config, refresh_token).await?;
77 let mut new_token: OAuthToken = refreshed.into();
78
79 if new_token.refresh_token.is_none() {
82 new_token.refresh_token = stored.refresh_token.clone();
83 }
84
85 save_oauth_token(app, config.provider_id, &new_token)?;
86
87 Ok(new_token.access_token)
88}