Skip to content
This repository was archived by the owner on Jan 2, 2025. It is now read-only.
1 change: 0 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
API_URL='required for self-serve only'
DEVICE_ID='used as user_id in analytics (for self-serve)'
ONBOARDING='if you want to force onboarding flow'

86 changes: 83 additions & 3 deletions apps/desktop/src-tauri/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use super::{plugin, relative_command_path, App, Manager, Payload, Runtime};

// a hack to get server/bleep/tests/desktop to run correctly
#[cfg(not(test))]
use super::{get_device_id, TELEMETRY};
use super::TELEMETRY;

#[cfg(test)]
static TELEMETRY: std::sync::RwLock<bool> = std::sync::RwLock::new(false);
Expand Down Expand Up @@ -60,8 +60,12 @@ where

let app = app.handle();
tokio::spawn(async move {
let initialized =
Application::initialize(Environment::insecure_local(), configuration).await;
let initialized = Application::initialize(
Environment::insecure_local(),
configuration,
get_device_id(),
)
.await;

if let Ok(backend) = initialized {
if let Err(_e) = backend.run().await {
Expand Down Expand Up @@ -142,3 +146,79 @@ pub fn initialize_analytics(key: String, data_plane: String) {
analytics::RudderHub::new_with_options(key, data_plane, options)
});
}

#[cfg(all(not(test), target_os = "macos"))]
fn get_device_id() -> String {
let ioreg = std::process::Command::new("ioreg")
.arg("-d2")
.arg("-c")
.arg("IOPlatformExpertDevice")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();
let command = std::process::Command::new("awk")
.arg("-F\"")
.arg("/IOPlatformUUID/{print $(NF-1)}")
.stdin(std::process::Stdio::from(ioreg.stdout.unwrap()))
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();

let output = command.wait_with_output().unwrap();
let result = std::str::from_utf8(&output.stdout).unwrap();
result.into()
}

#[cfg(all(not(test), target_os = "linux"))]
fn get_device_id() -> String {
use tracing::warn;

const STANDARD_MACHINE_ID: &str = "/etc/machine-id";
const LEGACY_MACHINE_ID: &str = "/var/lib/dbus/machine-id";

std::fs::read_to_string(STANDARD_MACHINE_ID)
.or_else(|_| {
warn!(
"could not find machine-id at `{}`, looking in `{}`",
STANDARD_MACHINE_ID, LEGACY_MACHINE_ID
);
std::fs::read_to_string(LEGACY_MACHINE_ID)
})
.unwrap_or_else(|_| {
warn!("failed to determine machine-id");
"unknown-machine-id".to_owned()
})
}

#[cfg(all(not(test), target_os = "windows"))]
fn get_device_id() -> String {
let command = std::process::Command::new("wmic")
.arg("csproduct")
.arg("get")
.arg("UUID")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();

let output = command.wait_with_output().unwrap();

// the output contains 3 lines:
//
// UUID
// EE134675-518A-8D49-B5E7-2475F745D1E6
// <newline>
//
// our goal is to preserve only the actual UUID.
let result = std::str::from_utf8(&output.stdout)
.unwrap()
.trim_start_matches("UUID") // remove the initial `UUID` header
.trim(); // remove the leading and trailing newlines
result.into()
}

// ensure that the leading header and trailer are stripped
#[cfg(windows)]
#[test]
fn device_id_on_single_line() {
assert_eq!(get_device_id().lines().count(), 1)
}
80 changes: 0 additions & 80 deletions apps/desktop/src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ async fn main() {
.setup(backend::bleep)
.invoke_handler(tauri::generate_handler![
show_folder_in_finder,
get_device_id,
enable_telemetry,
disable_telemetry,
])
Expand Down Expand Up @@ -88,82 +87,3 @@ fn show_folder_in_finder(path: String) {
.unwrap();
}
}

#[tauri::command]
#[cfg(target_os = "macos")]
fn get_device_id() -> String {
let ioreg = std::process::Command::new("ioreg")
.arg("-d2")
.arg("-c")
.arg("IOPlatformExpertDevice")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();
let command = std::process::Command::new("awk")
.arg("-F\"")
.arg("/IOPlatformUUID/{print $(NF-1)}")
.stdin(std::process::Stdio::from(ioreg.stdout.unwrap()))
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();

let output = command.wait_with_output().unwrap();
let result = std::str::from_utf8(&output.stdout).unwrap();
result.into()
}

#[tauri::command]
#[cfg(target_os = "linux")]
fn get_device_id() -> String {
use tracing::warn;

const STANDARD_MACHINE_ID: &str = "/etc/machine-id";
const LEGACY_MACHINE_ID: &str = "/var/lib/dbus/machine-id";

std::fs::read_to_string(STANDARD_MACHINE_ID)
.or_else(|_| {
warn!(
"could not find machine-id at `{}`, looking in `{}`",
STANDARD_MACHINE_ID, LEGACY_MACHINE_ID
);
std::fs::read_to_string(LEGACY_MACHINE_ID)
})
.unwrap_or_else(|_| {
warn!("failed to determine machine-id");
"unknown-machine-id".to_owned()
})
}

#[tauri::command]
#[cfg(target_os = "windows")]
fn get_device_id() -> String {
let command = std::process::Command::new("wmic")
.arg("csproduct")
.arg("get")
.arg("UUID")
.stdout(std::process::Stdio::piped())
.spawn()
.unwrap();

let output = command.wait_with_output().unwrap();

// the output contains 3 lines:
//
// UUID
// EE134675-518A-8D49-B5E7-2475F745D1E6
// <newline>
//
// our goal is to preserve only the actual UUID.
let result = std::str::from_utf8(&output.stdout)
.unwrap()
.trim_start_matches("UUID") // remove the initial `UUID` header
.trim(); // remove the leading and trailing newlines
result.into()
}

// ensure that the leading header and trailer are stripped
#[cfg(windows)]
#[test]
fn device_id_on_single_line() {
assert_eq!(get_device_id().lines().count(), 1)
}
18 changes: 1 addition & 17 deletions apps/desktop/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,6 @@ import TextSearch from './TextSearch';

function App() {
const [homeDirectory, setHomeDir] = useState('');
const [deviceId, setDeviceId] = useState('');
const [indexFolder, setIndexFolder] = useState('');
const [os, setOs] = useState({
arch: '',
Expand All @@ -91,20 +90,6 @@ function App() {

useEffect(() => {
homeDir().then(setHomeDir);
invoke('get_device_id')
.then((res) => {
if (res) {
setDeviceId(res.toString().trim());
} else {
let generatedId = getPlainFromStorage(DEVICE_ID);
if (!generatedId) {
generatedId = generateUniqueId();
savePlainToStorage(DEVICE_ID, generatedId);
}
setDeviceId(generatedId);
}
})
.catch(console.log);
Promise.all([
tauriOs.arch(),
tauriOs.type(),
Expand Down Expand Up @@ -134,7 +119,6 @@ function App() {
chooseFolder: openDialog,
indexFolder,
setIndexFolder,
deviceId,
listen,
os,
invokeTauriCommand: invoke,
Expand All @@ -146,7 +130,7 @@ function App() {
envConfig: {},
showNativeMessage: message,
}),
[homeDirectory, indexFolder, deviceId, os, release],
[homeDirectory, indexFolder, os, release],
);
return (
<>
Expand Down
1 change: 0 additions & 1 deletion client/src/Tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ function Tab({ deviceContextValue, isActive, tab }: Props) {
<div className={`${isActive ? '' : 'hidden'} `}>
<BrowserRouter>
<AnalyticsContextProvider
deviceId={deviceContextValue.deviceId}
forceAnalytics={deviceContextValue.forceAnalytics}
isSelfServe={deviceContextValue.isSelfServe}
envConfig={deviceContextValue.envConfig}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type Props = {
};

const Answer = ({ handleRetry, searchId, answer, error }: Props) => {
const { deviceId } = useContext(DeviceContext);
const { envConfig } = useContext(DeviceContext);
const { query } = useAppNavigation();
const [isUpvote, setIsUpvote] = useState(false);
const [isDownvote, setIsDownvote] = useState(false);
Expand Down Expand Up @@ -72,14 +72,14 @@ const Answer = ({ handleRetry, searchId, answer, error }: Props) => {
setIsDownvote(!isUpvote);
trackUpvote(isUpvote, query, answer || '', searchId);
return saveUpvote({
unique_id: deviceId,
unique_id: envConfig.tracking_id || '',
is_upvote: isUpvote,
query: query,
snippet_id: searchId,
text: answer || '',
});
},
[deviceId, query, answer, RiveUpvote, RiveDownvote],
[envConfig.tracking_id, query, answer, RiveUpvote, RiveDownvote],
);

return (
Expand Down
6 changes: 3 additions & 3 deletions client/src/components/ReportBugModal/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ const ReportBugModal = ({
const [serverCrashedMessage, setServerCrashedMessage] = useState('');
const { onBoardingState, isBugReportModalOpen, setBugReportModalOpen } =
useContext(UIContext);
const { deviceId, listen, os } = useContext(DeviceContext);
const { envConfig, listen, os } = useContext(DeviceContext);

useEffect(() => {
listen('server-crashed', (event) => {
Expand Down Expand Up @@ -76,13 +76,13 @@ const ReportBugModal = ({
if (serverCrashedMessage) {
saveCrashReport({
text: form.text,
unique_id: deviceId,
unique_id: envConfig.tracking_id || '',
info: serverCrashedMessage,
metadata: JSON.stringify(os),
});
} else {
const { emailError, ...values } = form;
saveBugReport({ ...values, unique_id: deviceId });
saveBugReport({ ...values, unique_id: envConfig.tracking_id || '' });
}
setSubmitted(true);
setServerCrashedMessage('');
Expand Down
6 changes: 3 additions & 3 deletions client/src/components/Settings/General/Profile/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { DeviceContext } from '../../../../context/deviceContext';

const ProfileSettings = () => {
const { onBoardingState, setOnBoardingState } = useContext(UIContext);
const { deviceId } = useContext(DeviceContext);
const { envConfig } = useContext(DeviceContext);
const [form, setForm] = useState({
firstName: '',
lastName: '',
Expand Down Expand Up @@ -57,10 +57,10 @@ const ProfileSettings = () => {
email: form.email,
first_name: form.firstName,
last_name: form.lastName,
unique_id: deviceId,
unique_id: envConfig.tracking_id || '',
});
},
[form],
[form, envConfig.tracking_id],
);

return (
Expand Down
6 changes: 4 additions & 2 deletions client/src/context/deviceContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ export type DeviceContextType = {
multiple?: boolean;
}) => Promise<null | string | string[]>;
homeDir: string;
deviceId: string;
listen: (
e: string,
cb: (event: { payload: { message: string } }) => void,
Expand All @@ -30,6 +29,10 @@ export type DeviceContextType = {
analytics_data_plane?: string;
analytics_key_fe?: string;
sentry_dsn_fe?: string;
user_login?: string | null;
org_name?: string | null;
tracking_id?: string;
device_id?: string;
};
showNativeMessage: (m: string, options?: any) => Promise<void> | void;
};
Expand All @@ -39,7 +42,6 @@ export const DeviceContext = createContext<DeviceContextType>({
openLink: (p) => {},
chooseFolder: (conf) => Promise.resolve(null),
homeDir: '$HOME',
deviceId: '',
listen: () => {},
os: {
arch: '',
Expand Down
Loading