summary refs log tree commit diff
path: root/app/src/lib.rs
blob: 91071faa14626ca409235dfdcb69e4be4eb2b9c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
mod oauth;
use oauth::{OAuthController, SigninResult};

mod persistence;

use persistence::{Account, PersistenceController};
use tauri_plugin_deep_link::DeepLinkExt;
use tauri_plugin_opener::OpenerExt;

use tauri::{Manager, State, AppHandle};

pub const OAUTH_CLIENT_NAME: &'static str = "foxfleet_test";

struct AppState {
    oauth_controller: OAuthController,
    persistence_controller: PersistenceController,
}

#[cfg_attr(mobile, tauri::mobile_entry_point)]
pub fn run() {
    tauri::Builder::default()
        .plugin(tauri_plugin_single_instance::init(|app, argv, cwd| {
            println!("{}, {argv:?}, {cwd}", app.package_info().name);
        }))
        .plugin(tauri_plugin_deep_link::init())
        .plugin(tauri_plugin_opener::init())
        .setup(|app| {
            let persistence_controller = PersistenceController::new(tauri::async_runtime::handle());
            let oauth_controller = OAuthController::new(tauri::async_runtime::handle(), persistence_controller.clone());
            app.manage(AppState {
                oauth_controller: oauth_controller.clone(),
                persistence_controller,
            });

            #[cfg(any(target_os = "linux", all(debug_assertions, windows)))]
            app.deep_link().register_all()?;
            app.deep_link().on_open_url(move |event| {
                if oauth_controller.handle_deeplink(&event.urls()).is_some() {
                    return
                }
            });
            Ok(())
        })
        .invoke_handler(tauri::generate_handler![start_account_auth, get_self, get_all_accounts])
        .run(tauri::generate_context!())
        .expect("Error starting")
}

#[tauri::command]
async fn get_all_accounts(state: State<'_, AppState>) -> Result<Vec<Account>, String> {
    Ok(state.persistence_controller.get_all_accounts().await)
}

#[tauri::command]
async fn start_account_auth(app_handle: AppHandle, state: State<'_, AppState>, instance_domain: &str) -> Result<Vec<String>, ()> {
    let add_result = state.oauth_controller.start_authorization(instance_domain).await;

    let state_nonce = match add_result {
        Ok(result) => {
            let opener = app_handle.opener();
            if let Err(_) = opener.open_url(result.auth_url, None::<&str>) {
                println!("Could not open authentication page");
                return Err(())
            }

            result.auth_state
        }
        Err(err) => {
            println!("Error adding server: {err}");
            return Err(())
        }
    };

    let signin_result = state.oauth_controller.finish_authorization(state_nonce).await;
    match signin_result {
        Ok(SigninResult {server_domain, username}) => {
            println!("Signed in successfully @{username}@{server_domain}");
            Ok(vec!(server_domain, username))
        }
        Err(err) => {
            println!("Error completing signin: {err}");
            Err(())
        }
    }
}

#[tauri::command]
async fn get_self(state: State<'_, AppState>, server_domain: String, username: String) -> Result<String, String> {
    let client = reqwest::Client::builder().user_agent("Foxfleet v0.0.1").build().expect("Could not construct client");

    let account = state.persistence_controller.get_account(&username, &server_domain).await
        .ok_or(format!("No account for @{username}@{server_domain}"))?;

    let api_key = state.persistence_controller.get_credential(account.api_credential_id).await?;
        
    if let Ok(result) = client.get("https://social.tempest.dev/api/v1/accounts/verify_credentials")
        .bearer_auth(api_key)
        .send().await {
            if let Ok(result) = result.text().await {
                return Ok(result)
            } else {
                return Err("Error decoding response".to_string());
            }
        } else {
            return Err("Error fetching account".to_string());
        }
}