128 lines
3.5 KiB
Rust
128 lines
3.5 KiB
Rust
//! Authentication flow manager
|
|
|
|
use crate::error::LauncherResult;
|
|
use crate::store::State;
|
|
use crate::store::credentials::{MinecraftCredentials, MinecraftLogin};
|
|
|
|
/// Begin a Microsoft authentication flow.
|
|
#[tracing::instrument]
|
|
pub async fn begin() -> LauncherResult<MinecraftLogin> {
|
|
let state = State::get().await?;
|
|
let mut store = state.credentials.write().await;
|
|
|
|
store.begin().await
|
|
}
|
|
|
|
/// Complete a Microsoft authentication flow to recieve [`MinecraftCredentials`].
|
|
#[tracing::instrument]
|
|
pub async fn finish(code: &str, flow: MinecraftLogin) -> LauncherResult<MinecraftCredentials> {
|
|
let state = State::get().await?;
|
|
let mut store = state.credentials.write().await;
|
|
|
|
store.finish(code, flow).await
|
|
}
|
|
|
|
/// Get the current default user if it exists by [`uuid::Uuid`].
|
|
#[tracing::instrument]
|
|
pub async fn get_default_user() -> LauncherResult<Option<uuid::Uuid>> {
|
|
let state = State::get().await?;
|
|
let store = state.credentials.read().await;
|
|
|
|
Ok(store.default_user)
|
|
}
|
|
|
|
/// Set the current default user by [`uuid::Uuid`].
|
|
#[tracing::instrument]
|
|
pub async fn set_default_user(user: Option<uuid::Uuid>) -> LauncherResult<()> {
|
|
let user = match user {
|
|
Some(user) => get_user(user).await?.map(|user| user.id),
|
|
None => None,
|
|
};
|
|
|
|
let state = State::get().await?;
|
|
let mut store = state.credentials.write().await;
|
|
|
|
store.default_user = user;
|
|
store.save().await?;
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Remove a user account by its [`uuid::Uuid`] from the global store.
|
|
#[tracing::instrument]
|
|
pub async fn remove_user(user: uuid::Uuid) -> LauncherResult<()> {
|
|
let state = State::get().await?;
|
|
let mut store = state.credentials.write().await;
|
|
|
|
store.remove(user).await?;
|
|
|
|
if store.default_user == Some(user) {
|
|
set_default_user(Some(user)).await?;
|
|
}
|
|
|
|
Ok(())
|
|
}
|
|
|
|
/// Get a list of user [`MinecraftCredentials`].
|
|
#[tracing::instrument]
|
|
pub async fn get_users() -> LauncherResult<Vec<MinecraftCredentials>> {
|
|
let state = State::get().await?;
|
|
let store = state.credentials.read().await;
|
|
|
|
Ok(store.users.values().cloned().collect())
|
|
}
|
|
|
|
/// Get a specifc user's [`MinecraftCredentials`] by their [`uuid::Uuid`].
|
|
/// Use [`crate::store::MinecraftState#refresh`] instead.
|
|
#[tracing::instrument]
|
|
pub async fn get_user(user: uuid::Uuid) -> LauncherResult<Option<MinecraftCredentials>> {
|
|
let state = State::get().await?;
|
|
let store = state.credentials.read().await;
|
|
|
|
let user = store.users.get(&user).cloned();
|
|
|
|
Ok(user)
|
|
}
|
|
|
|
/// Get a fake user for testing or offline mode.
|
|
#[must_use]
|
|
pub fn get_fake_user() -> MinecraftCredentials {
|
|
MinecraftCredentials {
|
|
id: uuid::Uuid::new_v4(),
|
|
username: "Player".to_string(),
|
|
access_token: "0".to_string(),
|
|
refresh_token: "0".to_string(),
|
|
expires: chrono::Utc::now() + chrono::Duration::days(1),
|
|
}
|
|
}
|
|
|
|
/// Refresh a specific user account by [`uuid::Uuid`].
|
|
#[tracing::instrument]
|
|
pub async fn refresh_account(user_id: uuid::Uuid) -> LauncherResult<Option<MinecraftCredentials>> {
|
|
let state = State::get().await?;
|
|
let mut store = state.credentials.write().await;
|
|
|
|
if let Some(user) = store.users.get(&user_id).cloned() {
|
|
store.refresh_token(&user).await
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
|
|
/// Refresh all user accounts.
|
|
#[tracing::instrument]
|
|
pub async fn refresh_accounts() -> LauncherResult<Vec<MinecraftCredentials>> {
|
|
let state = State::get().await?;
|
|
let mut store = state.credentials.write().await;
|
|
|
|
let users: Vec<MinecraftCredentials> = store.users.values().cloned().collect();
|
|
let mut refreshed_users = Vec::new();
|
|
|
|
for user in users {
|
|
if let Some(refreshed) = store.refresh_token(&user).await? {
|
|
refreshed_users.push(refreshed);
|
|
}
|
|
}
|
|
|
|
Ok(refreshed_users)
|
|
}
|