From 8f6100e5bc0ac5e1aae6cb5dc4d9eeff7ee36d0e Mon Sep 17 00:00:00 2001 From: Arnab Chakraborty <11457760+Rocky43007@users.noreply.github.com> Date: Mon, 12 Aug 2024 20:26:11 +0300 Subject: [PATCH] Remove keyring crate We found a different solution, as the keyring crate isn't supported on Android --- Cargo.lock | Bin 312635 -> 311587 bytes apps/desktop/src/App.tsx | 8 +- core/Cargo.toml | 2 - core/src/api/keys.rs | 134 +++++++++--------- core/src/api/mod.rs | 7 +- core/src/api/utils/mod.rs | 124 ++++++++-------- .../client/account/handlers/cookieHandler.ts | 65 ++++----- packages/client/src/core.ts | 2 - 8 files changed, 170 insertions(+), 172 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index d1d12d3d79b259acc41dd5cc191b08cff74545a6..93b7c6058f6ddc5028dc3173c9341b2456334b5f 100644 GIT binary patch delta 65 zcmV-H0KWgbiW8%P6R;E1voO_K_lK~}0k^Qt0#Aas3s3{t1D6b80~(jmSpx-!4O9b{ X4O9d>mR1A_w+~eWavZmTas;|kj2Rf1 delta 520 zcmZ9|J!=$E7zJQpWLJNMo~BUo8jOsp&dzV}Oqu)8p`yCIE8 znt)ZpAlFjy4@4|Rw6YL{SSV~O{s1c*1wnAs&gzuUIp_Iq@6Ds$VQ(=ovudsKw)E3B z%6Vb^aAoexs+f!iR|i9=NpgFgT0~+QP)jH}<+MhroDf`O(s31(Jzt1y@?Le+X{w{-=I-*=zfw(etNXcod@$U; zKfzJ4caV4EL7r|V#WX(KPtM1?kCPkMjB;&HZXht>B?PJ_Tnht? zDIK`-f`}}0iYZY)-8|iV&C>^Gm;NI4D~i_<01fDXF5}>p3PPBmf;NVuaV#+DBqKm2 p!}bX)t=39joE{7!nQDaPsRjo&I5sa*g7 diff --git a/apps/desktop/src/App.tsx b/apps/desktop/src/App.tsx index dd6ac6693..6a69a0af9 100644 --- a/apps/desktop/src/App.tsx +++ b/apps/desktop/src/App.tsx @@ -30,9 +30,7 @@ import SuperTokens from 'supertokens-web-js'; import EmailPassword from 'supertokens-web-js/recipe/emailpassword'; import Session from 'supertokens-web-js/recipe/session'; import ThirdParty from 'supertokens-web-js/recipe/thirdparty'; -import getCookieHandler, { - setAppReady -} from '@sd/interface/app/$libraryId/settings/client/account/handlers/cookieHandler'; +import getCookieHandler from '@sd/interface/app/$libraryId/settings/client/account/handlers/cookieHandler'; import getWindowHandler from '@sd/interface/app/$libraryId/settings/client/account/handlers/windowHandler'; import { useLocale } from '@sd/interface/hooks'; @@ -62,9 +60,7 @@ const startupError = (window as any).__SD_ERROR__ as string | undefined; export default function App() { useEffect(() => { // This tells Tauri to show the current window because it's finished loading - commands.appReady().then(() => { - setAppReady(); - }); + commands.appReady(); }, []); useEffect(() => { diff --git a/core/Cargo.toml b/core/Cargo.toml index 1bf128394..4de5482da 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -133,8 +133,6 @@ sysinfo = "0.29.11" # Update blocked due to API breaking changes tar = "0.4.41" tower-service = "0.3.2" tracing-appender = "0.2.3" -keyring = { version = "3.0.4", features = ["apple-native", "windows-native", "sync-secret-service"] } -whoami = "1.5.1" # Override features of transitive dependencies [dependencies.openssl] diff --git a/core/src/api/keys.rs b/core/src/api/keys.rs index 045b2b416..6ac655661 100644 --- a/core/src/api/keys.rs +++ b/core/src/api/keys.rs @@ -1,10 +1,10 @@ // TODO: Ensure this file has normalised caching setup before reenabling -use keyring::Entry; -use rspc::alpha::AlphaRouter; +// use keyring::Entry; +// use rspc::alpha::AlphaRouter; -use serde_json::Value; -use tracing::{debug, error}; +// use serde_json::Value; +// use tracing::{debug, error}; // use sd_crypto::keys::keymanager::{StoredKey, StoredKeyType}; // use sd_crypto::primitives::SECRET_KEY_IDENTIFIER; // use sd_crypto::types::{Algorithm, HashingAlgorithm, OnboardingConfig, SecretKeyString}; @@ -20,7 +20,7 @@ use tracing::{debug, error}; // use crate::{invalidate_query, prisma::key}; // use super::utils::library; -use super::{Ctx, R}; +// use super::{Ctx, R}; // #[derive(Type, Deserialize)] // pub struct KeyAddArgs { @@ -57,73 +57,73 @@ use super::{Ctx, R}; // status: bool, // } -pub(crate) fn mount() -> AlphaRouter { - R.router() - .procedure("set", { - R.mutation(|_, key: String| async move { - let username = whoami::username(); - let entry = match Entry::new("spacedrive-auth-service", username.as_str()) { - Ok(entry) => entry, - Err(e) => { - error!("Error creating entry: {}", e); - return Err(rspc::Error::new( - rspc::ErrorCode::InternalServerError, - "Error creating entry".to_string(), - )); - } - }; +// pub(crate) fn mount() -> AlphaRouter { +// R.router() +// .procedure("set", { +// R.mutation(|_, key: String| async move { +// let username = whoami::username(); +// let entry = match Entry::new("spacedrive-auth-service", username.as_str()) { +// Ok(entry) => entry, +// Err(e) => { +// error!("Error creating entry: {}", e); +// return Err(rspc::Error::new( +// rspc::ErrorCode::InternalServerError, +// "Error creating entry".to_string(), +// )); +// } +// }; - match entry.set_password(key.as_str()) { - Ok(_) => (), - Err(e) => { - error!("Error setting key: {}", e); - return Err(rspc::Error::new( - rspc::ErrorCode::InternalServerError, - "Error setting key".to_string(), - )); - } - } +// match entry.set_password(key.as_str()) { +// Ok(_) => (), +// Err(e) => { +// error!("Error setting key: {}", e); +// return Err(rspc::Error::new( +// rspc::ErrorCode::InternalServerError, +// "Error setting key".to_string(), +// )); +// } +// } - debug!( - "Key set successfully: key={key}, service={service}", - key = key, - service = "spacedrive-auth-service", - ); - Ok(()) - }) - }) - .procedure("get", { - R.query(|_, _: ()| async move { - let username = whoami::username(); - let entry = match Entry::new("spacedrive-auth-service", username.as_str()) { - Ok(entry) => entry, - Err(e) => { - error!("Error creating entry: {}", e); - return Err(rspc::Error::new( - rspc::ErrorCode::InternalServerError, - "Error creating entry".to_string(), - )); - } - }; +// debug!( +// "Key set successfully: key={key}, service={service}", +// key = key, +// service = "spacedrive-auth-service", +// ); +// Ok(()) +// }) +// }) +// .procedure("get", { +// R.query(|_, _: ()| async move { +// let username = whoami::username(); +// let entry = match Entry::new("spacedrive-auth-service", username.as_str()) { +// Ok(entry) => entry, +// Err(e) => { +// error!("Error creating entry: {}", e); +// return Err(rspc::Error::new( +// rspc::ErrorCode::InternalServerError, +// "Error creating entry".to_string(), +// )); +// } +// }; - let data = match entry.get_password() { - Ok(key) => key, - Err(e) => { - error!("Error retrieving key: {}. Does the key exist yet?", e); - return Ok("".to_string()); - } - }; +// let data = match entry.get_password() { +// Ok(key) => key, +// Err(e) => { +// error!("Error retrieving key: {}. Does the key exist yet?", e); +// return Ok("".to_string()); +// } +// }; - debug!( - "Key retrieved successfully: service={service}, data={_data}", - _data = data, - service = "spacedrive-auth-service", - ); +// debug!( +// "Key retrieved successfully: service={service}, data={_data}", +// _data = data, +// service = "spacedrive-auth-service", +// ); - Ok(data) - }) - }) -} +// Ok(data) +// }) +// }) +// } //NOTE(@Rocky43007): OLD PROCEDURES -> MAY BE USEFUL FOR REFERENCE AND COULD BE USED IN THE FUTURE // .procedure("list", { diff --git a/core/src/api/mod.rs b/core/src/api/mod.rs index 62f12d346..b8f0a36db 100644 --- a/core/src/api/mod.rs +++ b/core/src/api/mod.rs @@ -28,7 +28,8 @@ mod cloud; mod ephemeral_files; mod files; mod jobs; -mod keys; +// #[cfg(not(any(target_os = "ios", target_os = "android")))] +// mod keys; mod labels; mod libraries; pub mod locations; @@ -201,7 +202,6 @@ pub(crate) fn mount() -> Arc { .merge("tags.", tags::mount()) .merge("labels.", labels::mount()) // .merge("categories.", categories::mount()) - .merge("keys.", keys::mount()) .merge("locations.", locations::mount()) .merge("ephemeralFiles.", ephemeral_files::mount()) .merge("files.", files::mount()) @@ -225,6 +225,9 @@ pub(crate) fn mount() -> Arc { ); }); + // #[cfg(not(any(target_os = "ios", target_os = "android")))] + // let r = r.merge("keys.", keys::mount()); + let r = r .build( #[allow(clippy::let_and_return)] diff --git a/core/src/api/utils/mod.rs b/core/src/api/utils/mod.rs index f7bf924a3..a37888bbd 100644 --- a/core/src/api/utils/mod.rs +++ b/core/src/api/utils/mod.rs @@ -1,6 +1,8 @@ use std::path::Path; -use keyring::Entry; +// #[cfg(not(any(target_os = "ios", target_os = "android")))] +// use keyring::Entry; + use regex::Regex; use tokio::{fs, io}; use tracing::{debug, error}; @@ -39,63 +41,71 @@ pub async fn get_size(path: impl AsRef) -> Result { } } -pub fn get_access_token() -> Result { - let username = whoami::username(); - let entry = match Entry::new("spacedrive-auth-service", username.as_str()) { - Ok(entry) => entry, - Err(e) => { - error!("Error creating entry: {}", e); - return Err(rspc::Error::new( - rspc::ErrorCode::InternalServerError, - "Error creating entry".to_string(), - )); - } - }; +// pub fn get_access_token() -> Result { +// // If target is ios or android, return an error as this function is not supported on those platforms +// if cfg!(any(target_os = "ios", target_os = "android")) { +// return Err(rspc::Error::new( +// rspc::ErrorCode::InternalServerError, +// "Function not supported on this platform".to_string(), +// )); +// } else { +// let username = whoami::username(); +// let entry = match Entry::new("spacedrive-auth-service", username.as_str()) { +// Ok(entry) => entry, +// Err(e) => { +// error!("Error creating entry: {}", e); +// return Err(rspc::Error::new( +// rspc::ErrorCode::InternalServerError, +// "Error creating entry".to_string(), +// )); +// } +// }; - let data = match entry.get_password() { - Ok(key) => key, - Err(e) => { - error!("Error retrieving key: {}. Does the key exist yet?", e); - return Err(rspc::Error::new( - rspc::ErrorCode::InternalServerError, - "Error retrieving key".to_string(), - )); - } - }; +// let data = match entry.get_password() { +// Ok(key) => key, +// Err(e) => { +// error!("Error retrieving key: {}. Does the key exist yet?", e); +// return Err(rspc::Error::new( +// rspc::ErrorCode::InternalServerError, +// "Error retrieving key".to_string(), +// )); +// } +// }; - let re = match Regex::new(r#"st-access-token=([^;]+)"#) { - Ok(re) => re, - Err(e) => { - error!("Error creating regex: {}", e); - return Err(rspc::Error::new( - rspc::ErrorCode::InternalServerError, - "Error creating regex".to_string(), - )); - } - }; +// let re = match Regex::new(r#"st-access-token=([^;]+)"#) { +// Ok(re) => re, +// Err(e) => { +// error!("Error creating regex: {}", e); +// return Err(rspc::Error::new( +// rspc::ErrorCode::InternalServerError, +// "Error creating regex".to_string(), +// )); +// } +// }; - let token = match re.captures(&data) { - Some(captures) => match captures.get(1) { - Some(token) => token.as_str(), - None => { - error!("Error parsing Cookie String value: {}", "No token found"); - return Err(rspc::Error::new( - rspc::ErrorCode::InternalServerError, - "Error parsing Cookie String value".to_string(), - )); - } - }, - None => { - error!( - "Error parsing Cookie String value: {}", - "No token cookie string found" - ); - return Err(rspc::Error::new( - rspc::ErrorCode::InternalServerError, - "Error parsing Cookie String value".to_string(), - )); - } - }; +// let token = match re.captures(&data) { +// Some(captures) => match captures.get(1) { +// Some(token) => token.as_str(), +// None => { +// error!("Error parsing Cookie String value: {}", "No token found"); +// return Err(rspc::Error::new( +// rspc::ErrorCode::InternalServerError, +// "Error parsing Cookie String value".to_string(), +// )); +// } +// }, +// None => { +// error!( +// "Error parsing Cookie String value: {}", +// "No token cookie string found" +// ); +// return Err(rspc::Error::new( +// rspc::ErrorCode::InternalServerError, +// "Error parsing Cookie String value".to_string(), +// )); +// } +// }; - Ok(token.to_string()) -} \ No newline at end of file +// Ok(token.to_string()) +// } +// } diff --git a/interface/app/$libraryId/settings/client/account/handlers/cookieHandler.ts b/interface/app/$libraryId/settings/client/account/handlers/cookieHandler.ts index 97bc96b3e..a0ca2abe9 100644 --- a/interface/app/$libraryId/settings/client/account/handlers/cookieHandler.ts +++ b/interface/app/$libraryId/settings/client/account/handlers/cookieHandler.ts @@ -1,15 +1,18 @@ import { CookieHandlerInterface } from "supertokens-website/utils/cookieHandler/types"; -import { nonLibraryClient } from '@sd/client' -let APP_READY = false; +const frontendCookiesKey = "frontendCookies"; -async function getCookiesFromStorage(): Promise { - if (!APP_READY) { - return ""; - } - const cookiesFromStorage = await nonLibraryClient.query(['keys.get']) +/** + * Tauri handles cookies differently than in browser environments. The SuperTokens + * SDK uses frontend cookies, to make sure everything work correctly we add custom + * cookie handling and store cookies in local storage instead (This is not a problem + * since these are frontend cookies and not server side cookies) + */ +function getCookiesFromStorage(): string { + const cookiesFromStorage = window.localStorage.getItem(frontendCookiesKey); - if (cookiesFromStorage.length === 0) { + if (cookiesFromStorage === null) { + window.localStorage.setItem(frontendCookiesKey, "[]"); return ""; } @@ -22,54 +25,47 @@ async function getCookiesFromStorage(): Promise { for (let cookieIndex = 0; cookieIndex < cookieArrayInStorage.length; cookieIndex++) { const currentCookieString = cookieArrayInStorage[cookieIndex]; - const parts = currentCookieString?.split(";") ?? []; + const parts = currentCookieString?.split(";"); let expirationString: string = ""; - for (let partIndex = 0; partIndex < parts.length; partIndex++) { - const currentPart = parts[partIndex]; + for (let partIndex = 0; partIndex < parts!.length; partIndex++) { + const currentPart = parts![partIndex]; - if (currentPart?.toLocaleLowerCase().includes("expires=")) { - expirationString = currentPart; + if (currentPart!.toLocaleLowerCase().includes("expires=")) { + expirationString = currentPart!; break; } } if (expirationString !== "") { const expirationValueString = expirationString.split("=")[1]; - const expirationDate = expirationValueString ? new Date(expirationValueString) : null; + const expirationDate = new Date(expirationValueString!); const currentTimeInMillis = Date.now(); // if the cookie has expired, we skip it - if (expirationDate && expirationDate.getTime() < currentTimeInMillis) { + if (expirationDate.getTime() < currentTimeInMillis) { continue; } } - if (currentCookieString !== undefined) { - cookieArrayToReturn.push(currentCookieString); - } + cookieArrayToReturn.push(currentCookieString!); } /** * After processing and removing expired cookies we need to update the cookies * in storage so we dont have to process the expired ones again */ - await nonLibraryClient.mutation(['keys.set', JSON.stringify(cookieArrayToReturn)]) + window.localStorage.setItem(frontendCookiesKey, JSON.stringify(cookieArrayToReturn)); return cookieArrayToReturn.join("; "); } -async function setCookieToStorage(cookieString: string): Promise { - if (!APP_READY) { - return; - } - const cookieName = cookieString.split(";")[0]?.split("=")[0]; - - const cookiesFromStorage = await nonLibraryClient.query(['keys.get']) - +function setCookieToStorage(cookieString: string) { + const cookieName = cookieString.split(";")[0]!.split("=")[0]; + const cookiesFromStorage = window.localStorage.getItem(frontendCookiesKey); let cookiesArray: string[] = []; - if (cookiesFromStorage.length !== 0) { + if (cookiesFromStorage !== null) { const cookiesArrayFromStorage: string[] = JSON.parse(cookiesFromStorage); cookiesArray = cookiesArrayFromStorage; } @@ -79,7 +75,7 @@ async function setCookieToStorage(cookieString: string): Promise { for (let i = 0; i < cookiesArray.length; i++) { const currentCookie = cookiesArray[i]; - if (currentCookie?.indexOf(`${cookieName}=`) !== -1) { + if (currentCookie!.indexOf(`${cookieName}=`) !== -1) { cookieIndex = i; break; } @@ -97,21 +93,18 @@ async function setCookieToStorage(cookieString: string): Promise { cookiesArray.push(cookieString); } - await nonLibraryClient.mutation(['keys.set', JSON.stringify(cookiesArray)]) + window.localStorage.setItem(frontendCookiesKey, JSON.stringify(cookiesArray)); } export default function getCookieHandler(original: CookieHandlerInterface): CookieHandlerInterface { return { ...original, getCookie: async function () { - return getCookiesFromStorage(); + const cookies = getCookiesFromStorage(); + return cookies; }, setCookie: async function (cookieString: string) { - return setCookieToStorage(cookieString); + setCookieToStorage(cookieString); }, }; } - -export function setAppReady() { - APP_READY = true; -} diff --git a/packages/client/src/core.ts b/packages/client/src/core.ts index 42560c8aa..b26da04c6 100644 --- a/packages/client/src/core.ts +++ b/packages/client/src/core.ts @@ -23,7 +23,6 @@ export type Procedures = { { key: "invalidation.test-invalidate", input: never, result: number } | { key: "jobs.isActive", input: LibraryArgs, result: boolean } | { key: "jobs.reports", input: LibraryArgs, result: JobGroup[] } | - { key: "keys.get", input: never, result: string } | { key: "labels.count", input: LibraryArgs, result: number } | { key: "labels.get", input: LibraryArgs, result: Label | null } | { key: "labels.getForObject", input: LibraryArgs, result: Label[] } | @@ -111,7 +110,6 @@ export type Procedures = { { key: "jobs.objectValidator", input: LibraryArgs, result: null } | { key: "jobs.pause", input: LibraryArgs, result: null } | { key: "jobs.resume", input: LibraryArgs, result: null } | - { key: "keys.set", input: string, result: null } | { key: "labels.delete", input: LibraryArgs, result: null } | { key: "library.create", input: CreateLibraryArgs, result: LibraryConfigWrapped } | { key: "library.delete", input: string, result: null } |