From 9df6ea8847e20c52034881629a7da8c57e28a2ac Mon Sep 17 00:00:00 2001 From: Klesti Selimaj Date: Sat, 4 Apr 2026 18:06:37 +0200 Subject: [PATCH] Implementing auth --- src-tauri/src/launcher/auth.rs | 7 +- src/components/layout/AccountDropdown.tsx | 112 +++++++++++++++++----- src/lib/auth.ts | 18 +++- 3 files changed, 108 insertions(+), 29 deletions(-) diff --git a/src-tauri/src/launcher/auth.rs b/src-tauri/src/launcher/auth.rs index 45cd859..ecd74bc 100644 --- a/src-tauri/src/launcher/auth.rs +++ b/src-tauri/src/launcher/auth.rs @@ -4,6 +4,7 @@ use reqwest::Client; use tauri::command; use lyceris::auth::microsoft::{authenticate, create_link, refresh, validate, MinecraftAccount}; +use tauri_plugin_opener::open_url; use crate::launcher::LAUNCHER_DIR; @@ -36,7 +37,11 @@ fn save_accounts(accounts: &[MinecraftAccount]) -> Result<(), String> { #[command] pub fn auth_create_link() -> Result { - create_link().map_err(|e| e.to_string()) + let link = create_link().map_err(|e| e.to_string())?; + + open_url(&link, None::).map_err(|e| e.to_string())?; + + Ok(link) } #[command] diff --git a/src/components/layout/AccountDropdown.tsx b/src/components/layout/AccountDropdown.tsx index 6f075e3..89eebe9 100644 --- a/src/components/layout/AccountDropdown.tsx +++ b/src/components/layout/AccountDropdown.tsx @@ -1,6 +1,13 @@ +import { useEffect, useState } from "react"; import { User, LogOut } from "lucide-react"; import { cn } from "@/lib/utils"; import { Props } from "./props"; +import { authList, authRemove, authCreateLink } from "@/lib/auth"; + +interface Account { + uuid: string; + username: string; +} function UserComponent({ username, @@ -36,63 +43,120 @@ export default function AccountDropdown({ setIsAccountDropdownOpen, accountRef, }: Props) { + const [accounts, setAccounts] = useState([]); + const [active, setActive] = useState(null); + + // Load accounts + useEffect(() => { + loadAccounts(); + }, []); + + async function loadAccounts() { + const accs = await authList(); + setAccounts(accs); + + if (accs.length && !active) { + setActive(accs[0]); // default + } + } + + // Switch account + function switchAccount(acc: Account) { + setActive(acc); + setIsAccountDropdownOpen(false); + } + + // Logout (remove account) + async function logout() { + if (!active) return; + + await authRemove(active.uuid); + + const updated = await authList(); + setAccounts(updated); + setActive(updated[0] || null); + } + + // Add account (open Microsoft login) + async function addAccount() { + const url = await authCreateLink(); + console.log("Opening auth URL:", url); + } + + const otherAccounts = accounts.filter((a) => a.uuid !== active?.uuid); + return (
+ {/* Glow */}
+ {/* Button */} + {/* Dropdown */}
{/* Current account */} -
+ {active && ( + + )} + + {/* Other accounts */} + {otherAccounts.map((acc) => ( switchAccount(acc)} /> -
+ ))} - {/* Accounts (current account should be filtered) */} - -
- {}} - /> -
- - {/* Account Options */} - - - diff --git a/src/lib/auth.ts b/src/lib/auth.ts index 9a7d33b..311c8ee 100644 --- a/src/lib/auth.ts +++ b/src/lib/auth.ts @@ -1,5 +1,15 @@ import { invoke } from "@tauri-apps/api/core"; +export interface MinecraftAccount { + xuid: string; + exp: number; + uuid: string; + username: string; + access_token: string; + refresh_token: string; + client_id: string; +} + /** * Create Microsoft login URL */ @@ -10,21 +20,21 @@ export async function authCreateLink(): Promise { /** * Exchange auth code for account */ -export async function authLogin(code: string) { +export async function authLogin(code: string): Promise { return await invoke("auth_login", { code }); } /** * Refresh account by UUID */ -export async function authRefresh(uuid: string) { +export async function authRefresh(uuid: string): Promise { return await invoke("auth_refresh", { uuid }); } /** * Get all stored accounts */ -export async function authList() { +export async function authList(): Promise { return await invoke("auth_list"); } @@ -45,6 +55,6 @@ export async function authValidate(uuid: string): Promise { /** * Get valid account (auto-refresh if needed) */ -export async function authGetValid(uuid: string) { +export async function authGetValid(uuid: string): Promise { return await invoke("auth_get_valid", { uuid }); }