Franknoirot/fix prod tauri auth (#531)
* Invoke tauri-based logout if in tauri * Add kittycad Rust library * Add logout and get_user Tauri commands * Invoke get_user instead of fetching in Tauri * @jessfraz review Signed-off-by: Frank Noirot <frank@kittycad.io> * Remove unnecessary logout command * Fix rushed last commit --------- Signed-off-by: Frank Noirot <frank@kittycad.io>
This commit is contained in:
712
src-tauri/Cargo.lock
generated
712
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@ -16,13 +16,14 @@ tauri-build = { version = "1.4.0", features = [] }
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
|
kittycad = "0.2.25"
|
||||||
oauth2 = "4.4.2"
|
oauth2 = "4.4.2"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
tauri = { version = "1.4.1", features = ["dialog-all", "fs-all", "http-request", "path-all", "shell-open", "shell-open-api", "updater", "devtools"] }
|
tauri = { version = "1.4.1", features = ["dialog-all", "fs-all", "http-request", "path-all", "shell-open", "shell-open-api", "updater", "devtools"] }
|
||||||
|
tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
|
||||||
tokio = { version = "1.32.0", features = ["time"] }
|
tokio = { version = "1.32.0", features = ["time"] }
|
||||||
toml = "0.8.0"
|
toml = "0.8.0"
|
||||||
tauri-plugin-fs-extra = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" }
|
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
|
# this feature is used for production builds or when `devPath` points to the filesystem and the built-in dev server is disabled.
|
||||||
|
@ -85,6 +85,24 @@ async fn login(app: tauri::AppHandle, host: &str) -> Result<String, InvokeError>
|
|||||||
Ok(token)
|
Ok(token)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///This command returns the KittyCAD user info given a token.
|
||||||
|
/// The string returned from this method is the user info as a json string.
|
||||||
|
#[tauri::command]
|
||||||
|
async fn get_user(token: Option<String>) -> Result<kittycad::types::User, InvokeError> {
|
||||||
|
println!("Getting user info...");
|
||||||
|
|
||||||
|
// use kittycad library to fetch the user info from /user/me
|
||||||
|
let client = kittycad::Client::new(token.unwrap());
|
||||||
|
|
||||||
|
let user_info: kittycad::types::User = client
|
||||||
|
.users()
|
||||||
|
.get_self()
|
||||||
|
.await
|
||||||
|
.map_err(|e| InvokeError::from_anyhow(e.into()))?;
|
||||||
|
|
||||||
|
Ok(user_info)
|
||||||
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
@ -97,7 +115,12 @@ fn main() {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.invoke_handler(tauri::generate_handler![login, read_toml, read_txt_file])
|
.invoke_handler(tauri::generate_handler![
|
||||||
|
get_user,
|
||||||
|
login,
|
||||||
|
read_toml,
|
||||||
|
read_txt_file
|
||||||
|
])
|
||||||
.plugin(tauri_plugin_fs_extra::init())
|
.plugin(tauri_plugin_fs_extra::init())
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
|
@ -24,6 +24,9 @@ import {
|
|||||||
StateFrom,
|
StateFrom,
|
||||||
} from 'xstate'
|
} from 'xstate'
|
||||||
import { useCommandsContext } from 'hooks/useCommandsContext'
|
import { useCommandsContext } from 'hooks/useCommandsContext'
|
||||||
|
import { invoke } from '@tauri-apps/api'
|
||||||
|
import { isTauri } from 'lib/isTauri'
|
||||||
|
import { VITE_KC_API_BASE_URL } from 'env'
|
||||||
|
|
||||||
type MachineContext<T extends AnyStateMachine> = {
|
type MachineContext<T extends AnyStateMachine> = {
|
||||||
state: StateFrom<T>
|
state: StateFrom<T>
|
||||||
@ -108,6 +111,7 @@ export const GlobalStateProvider = ({
|
|||||||
actions: {
|
actions: {
|
||||||
goToSignInPage: () => {
|
goToSignInPage: () => {
|
||||||
navigate(paths.SIGN_IN)
|
navigate(paths.SIGN_IN)
|
||||||
|
|
||||||
logout()
|
logout()
|
||||||
},
|
},
|
||||||
goToIndexPage: () => {
|
goToIndexPage: () => {
|
||||||
@ -149,10 +153,12 @@ export const GlobalStateProvider = ({
|
|||||||
export default GlobalStateProvider
|
export default GlobalStateProvider
|
||||||
|
|
||||||
export function logout() {
|
export function logout() {
|
||||||
const url = withBaseUrl('/logout')
|
|
||||||
localStorage.removeItem(TOKEN_PERSIST_KEY)
|
localStorage.removeItem(TOKEN_PERSIST_KEY)
|
||||||
return fetch(url, {
|
return (
|
||||||
method: 'POST',
|
!isTauri() &&
|
||||||
credentials: 'include',
|
fetch(withBaseUrl('/logout'), {
|
||||||
})
|
method: 'POST',
|
||||||
|
credentials: 'include',
|
||||||
|
})
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ import { createMachine, assign } from 'xstate'
|
|||||||
import { Models } from '@kittycad/lib'
|
import { Models } from '@kittycad/lib'
|
||||||
import withBaseURL from '../lib/withBaseURL'
|
import withBaseURL from '../lib/withBaseURL'
|
||||||
import { CommandBarMeta } from '../lib/commands'
|
import { CommandBarMeta } from '../lib/commands'
|
||||||
|
import { isTauri } from 'lib/isTauri'
|
||||||
|
import { invoke } from '@tauri-apps/api'
|
||||||
|
|
||||||
const SKIP_AUTH =
|
const SKIP_AUTH =
|
||||||
import.meta.env.VITE_KC_SKIP_AUTH === 'true' && import.meta.env.DEV
|
import.meta.env.VITE_KC_SKIP_AUTH === 'true' && import.meta.env.DEV
|
||||||
@ -115,16 +117,25 @@ async function getUser(context: UserContext) {
|
|||||||
const headers: { [key: string]: string } = {
|
const headers: { [key: string]: string } = {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
}
|
}
|
||||||
if (!context.token && '__TAURI__' in window) throw 'not log in'
|
|
||||||
|
if (!context.token && isTauri()) throw new Error('No token found')
|
||||||
if (context.token) headers['Authorization'] = `Bearer ${context.token}`
|
if (context.token) headers['Authorization'] = `Bearer ${context.token}`
|
||||||
if (SKIP_AUTH) return LOCAL_USER
|
if (SKIP_AUTH) return LOCAL_USER
|
||||||
const response = await fetch(url, {
|
|
||||||
method: 'GET',
|
|
||||||
credentials: 'include',
|
|
||||||
headers,
|
|
||||||
})
|
|
||||||
|
|
||||||
const user = await response.json()
|
const userPromise = !isTauri()
|
||||||
|
? fetch(url, {
|
||||||
|
method: 'GET',
|
||||||
|
credentials: 'include',
|
||||||
|
headers,
|
||||||
|
})
|
||||||
|
.then((res) => res.json())
|
||||||
|
.catch((err) => console.error('error from Browser getUser', err))
|
||||||
|
: invoke<Models['User_type'] | Record<'error_code', unknown>>('get_user', {
|
||||||
|
token: context.token,
|
||||||
|
}).catch((err) => console.error('error from Tauri getUser', err))
|
||||||
|
|
||||||
|
const user = await userPromise
|
||||||
|
|
||||||
if ('error_code' in user) throw new Error(user.message)
|
if ('error_code' in user) throw new Error(user.message)
|
||||||
|
|
||||||
return user
|
return user
|
||||||
|
Reference in New Issue
Block a user