Skip to content

Commit

Permalink
Auto Launching
Browse files Browse the repository at this point in the history
  • Loading branch information
ItsRiprod committed Sep 20, 2024
1 parent 9fd4c3b commit f4f31b0
Show file tree
Hide file tree
Showing 17 changed files with 446 additions and 206 deletions.
232 changes: 145 additions & 87 deletions DeskThingServer/package-lock.json

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion DeskThingServer/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "deskthing",
"version": "0.8.4",
"version": "0.9.0",
"description": "A DeskThing server UI to interface with the DeskThing car thing app",
"main": "./out/main/index.js",
"author": "Riprod",
Expand All @@ -20,7 +20,9 @@
"dependencies": {
"@electron-toolkit/preload": "^3.0.0",
"@electron-toolkit/utils": "^3.0.0",
"@types/auto-launch": "^5.0.5",
"adm-zip": "^0.5.16",
"auto-launch": "^5.0.6",
"axios": "^1.7.2",
"cors": "^2.8.5",
"cross-unzip": "^0.2.1",
Expand Down
18 changes: 13 additions & 5 deletions DeskThingServer/src/main/handlers/apps/appState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export class AppHandler {
* Loads the apps from file
*/
async loadApps(): Promise<void> {
console.log('Loading apps...')
console.log('[appState] [loadApps]: Loading apps...')
const { getAppData } = await import('../configHandler')
const data = await getAppData()
data.apps.forEach((app) => {
Expand All @@ -48,9 +48,6 @@ export class AppHandler {
this.order.push(app.name)
}
})

// Sort the order array based on prefIndex
this.order.sort((a, b) => this.apps[a].prefIndex - this.apps[b].prefIndex)
}

private async saveAppsToFile(): Promise<void> {
Expand Down Expand Up @@ -100,14 +97,17 @@ export class AppHandler {
* @returns all apps
*/
getAll(): AppInstance[] {
console.log('Getting all in the order of: ', this.order)
return this.order.map((name) => this.apps[name])
}

getAllBase(): App[] {
return this.order.map((name) => {
const baseApp = this.order.map((name) => {
const { func: _func, ...baseApp } = this.apps[name]
return baseApp
})
console.log('The base order is', this.order)
return baseApp
}
remove(name: string): boolean {
if (!(name in this.apps)) {
Expand Down Expand Up @@ -143,6 +143,14 @@ export class AppHandler {
// Save new order
this.saveAppsToFile()
}
setItemOrder(name: string, newIndex: number): void {
const index = this.order.indexOf(name)
if (index !== -1) {
this.order.splice(index, 1)
this.order.splice(newIndex, 0, name)
}
this.saveAppsToFile()
}
getOrder(): string[] {
return this.order
}
Expand Down
14 changes: 9 additions & 5 deletions DeskThingServer/src/main/handlers/authHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,15 @@ const initializeServer = async (): Promise<void> => {
}

dataListener.on(MESSAGE_TYPES.SETTINGS, (newSettings) => {
if (newSettings.payload.callbackPort != callBackPort) {
callBackPort = newSettings.payload.callbackPort
startServer()
} else {
dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, 'CALLBACK: Not starting - port is not changed')
try {
if (newSettings.payload.callbackPort != callBackPort) {
callBackPort = newSettings.payload.callbackPort
startServer()
} else {
dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, 'CALLBACK: Not starting - port is not changed')
}
} catch (error) {
dataListener.asyncEmit(MESSAGE_TYPES.ERROR, 'CALLBACK: Error updating with settings', error)
}
})

Expand Down
2 changes: 1 addition & 1 deletion DeskThingServer/src/main/handlers/configHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ const readData = (): AppData => {
const data = readFromFile<AppData>(dataFilePath)
if (!data) {
// File does not exist, create it with default data
console.log('File does not exist, creating it with default data')
writeToFile(defaultData, dataFilePath)
return defaultData
}

// If data is of type AppData, return it
return data as AppData
} catch (err) {
Expand Down
24 changes: 21 additions & 3 deletions DeskThingServer/src/main/handlers/firewallHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,24 @@ async function checkFirewallRuleExists(port: number): Promise<boolean> {
}

// Firewall setup function
async function setupFirewall(port: number): Promise<void> {
async function setupFirewall(
port: number,
reply: (params: { status: boolean; data: string; final: boolean; error?: string | Error }) => void
): Promise<void> {
const platform = os.platform()
const inboundRuleName = 'Deskthing Server Inbound'
const outboundRuleName = 'Deskthing Server Outbound'

try {
reply && reply({ status: true, data: 'Checking if rules exist', final: false })
const ruleExists = await checkFirewallRuleExists(port)
if (ruleExists) {
dataListener.asyncEmit(
MESSAGE_TYPES.LOGGING,
`FIREWALL: Firewall rule for port ${port} verified successfully`
)
console.log(`Firewall rule for port ${port} verified successfully`)
return
reply && reply({ status: true, data: 'Verified that the rule exists!', final: false })
} else {
dataListener.asyncEmit(
MESSAGE_TYPES.ERROR,
Expand All @@ -86,6 +90,7 @@ async function setupFirewall(port: number): Promise<void> {
*/
reply && reply({ status: true, data: 'Running setup for windows', final: false })
const script = `
$inboundRuleName = "${inboundRuleName}"
$outboundRuleName = "${outboundRuleName}"
Expand Down Expand Up @@ -113,10 +118,13 @@ async function setupFirewall(port: number): Promise<void> {
`FIREWALL: Firewall rules set up successfully on Windows`
)
console.log('Firewall rules set up successfully on Windows')

reply && reply({ status: true, data: 'Firewall ran without error', final: false })
} finally {
fs.unlinkSync(tempScriptPath)
}
} else if (platform === 'linux') {
reply && reply({ status: true, data: 'Running setup scripts for Linux', final: false })
// Bash script for iptables on Linux
const script = `
#!/bin/bash
Expand All @@ -137,6 +145,12 @@ async function setupFirewall(port: number): Promise<void> {
)
console.log('Firewall rules set up successfully on Linux')
} else if (platform === 'darwin') {
reply &&
reply({
status: true,
data: 'Running setup scripts for MacOS (WARN: RNDIS does not work on MacOS)',
final: false
})
// Bash script for pfctl on macOS
const script = `
#!/bin/bash
Expand All @@ -163,8 +177,12 @@ async function setupFirewall(port: number): Promise<void> {
MESSAGE_TYPES.ERROR,
`FIREWALL: Error encountered trying to setup firewall for ${port}! Run administrator and try again`
)
if (error instanceof Error) {
reply && reply({ status: false, data: 'Error in firewall', error: error, final: true })
}
console.error(error)
}
}

reply && reply({ status: true, data: 'Firewall run successfully!', final: true })
}
export { setupFirewall }
23 changes: 2 additions & 21 deletions DeskThingServer/src/main/handlers/websocketServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ const sendError = async (socket, error): Promise<void> => {
const sendPrefData = async (socket: WebSocket | null = null): Promise<void> => {
try {
const appData = await AppState.getAllBase()
console.log('Client Request: ', appData)
const config = await readData()
if (!appData) {
throw new Error('Invalid configuration format')
Expand Down Expand Up @@ -454,27 +455,7 @@ const setupServer = async (): Promise<void> => {
case 'update_pref_index':
if (parsedMessage.payload) {
const { app: appName, index: newIndex } = parsedMessage.payload
const appData = await AppState.get(appName)

if (
appData &&
appData.manifest &&
(appData.manifest.isWebApp || appData.manifest.isLocalApp)
) {
// Update the existing app's index
appData.prefIndex = newIndex
await AppState.add(appData)

dataListener.emit(
MESSAGE_TYPES.LOGGING,
`WEBSOCKET: Updated app indexes and sent to client`
)
console.log('Updated app indexes and sent to client')

await sendPrefData(socket) // Send updated data to the client
} else {
console.log(`WSOCKET: App ${appName} is not valid or not allowed`)
}
AppState.setItemOrder(appName, newIndex)
}
break
default:
Expand Down
57 changes: 47 additions & 10 deletions DeskThingServer/src/main/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ const IPC_CHANNELS = {
SHUTDOWN: 'shutdown',
DEV_ADD_APP: 'dev-add-app',
SEND_TO_APP: 'send-to-app',
OPEN_LOG_FOLDER: 'open-log-folder'
OPEN_LOG_FOLDER: 'open-log-folder',
REFRESH_FIREWALL: 'refresh-firewall'
}

function createMainWindow(): BrowserWindow {
Expand Down Expand Up @@ -265,7 +266,6 @@ async function initializeDoc(): Promise<void> {

async function setupIpcHandlers(): Promise<void> {
const settingsStore = await import('./stores/settingsStore')
const { getAppData } = await import('./handlers/configHandler')
const { handleZipFromUrl, sendMessageToApp, handleZip, AppHandler } = await import(
'./handlers/apps'
)
Expand All @@ -285,14 +285,6 @@ async function setupIpcHandlers(): Promise<void> {
const dataListener = (await import('./utils/events')).default
const { MESSAGE_TYPES } = await import('./utils/events')

const { setupFirewall } = await import('./handlers/firewallHandler')
const payload = (await settingsStore.default.getSettings()).payload as Settings
if (payload) {
setupFirewall(payload.devicePort).catch(console.error)
} else {
dataListener.asyncEmit(MESSAGE_TYPES.ERROR, 'No settings found!')
}

ipcMain.on(IPC_CHANNELS.PING, () => console.log('pong'))
ipcMain.on(IPC_CHANNELS.GET_CONNECTIONS, async (event) => {
const clients = await ConnectionStore.getClients()
Expand All @@ -316,6 +308,7 @@ async function setupIpcHandlers(): Promise<void> {
})
ipcMain.on(IPC_CHANNELS.GET_APPS, (event) => {
event.reply('logging', { status: true, data: 'Getting data', final: false })
console.log('Getting app data')
const data = appHandler.getAllBase()
event.reply('logging', { status: true, data: 'Finished', final: true })
event.reply('app-data', { status: true, data: data, final: true })
Expand Down Expand Up @@ -418,6 +411,49 @@ async function setupIpcHandlers(): Promise<void> {
return null
}
})
ipcMain.handle(IPC_CHANNELS.REFRESH_FIREWALL, async (event) => {
try {
const { setupFirewall } = await import('./handlers/firewallHandler')
event.sender.emit('logging', { status: true, data: 'Refreshing Firewall', final: false })
const payload = (await settingsStore.default.getSettings()).payload as Settings
if (payload) {
dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, '[firewall] Setting up firewall')
try {
await setupFirewall(payload.devicePort, (message) => {
if (event.sender.isDestroyed()) return
event.sender.send('logging', message)
})
} catch (firewallError) {
console.log(firewallError)
if (!(firewallError instanceof Error)) return

dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `FIREWALL: ${firewallError.message}`)
event.sender.emit('logging', {
status: false,
data: 'Error in firewall',
error: firewallError.message,
final: true
})
return
}
} else {
dataListener.asyncEmit(MESSAGE_TYPES.ERROR, '[firewall] No settings found!')
event.sender.emit('logging', {
status: false,
data: 'Error in firewall',
error: 'No settings found!',
final: true
})
}
} catch (error) {
dataListener.asyncEmit(
MESSAGE_TYPES.ERROR,
'SERVER: [firewall] Error saving manifest' + error
)
console.error('[Firewall] Error setting client manifest:', error)
event.sender.emit('logging', { status: false, data: 'Unfinished', error: error, final: true })
}
})
ipcMain.handle(
IPC_CHANNELS.SET_CLIENT_MANIFEST,
async (event, manifest: Partial<ServerManifest>) => {
Expand Down Expand Up @@ -462,6 +498,7 @@ async function setupIpcHandlers(): Promise<void> {
return await settingsStore.default.getSettings()
})
ipcMain.handle(IPC_CHANNELS.SAVE_SETTINGS, async (_event, settings) => {
console.log('Saving settings', settings)
return await settingsStore.default.saveSettings(settings)
})
ipcMain.handle(IPC_CHANNELS.GET_MAPS, async (event) => {
Expand Down
22 changes: 22 additions & 0 deletions DeskThingServer/src/main/stores/settingsStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ class SettingsStore {
}

public updateSetting(key: string, value: any): void {
if (key === 'autoStart') {
this.updateAutoLaunch(value)
}
this.settings[key] = value
dataListener.asyncEmit(MESSAGE_TYPES.SETTINGS, {
type: 'settings',
Expand All @@ -76,13 +79,18 @@ class SettingsStore {
try {
const data = await readFromFile<Settings>(this.settingsFilePath)
dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, 'SETTINGS: Loaded settings!')

if (!data || data.version !== settingsVersion) {
// File does not exist, create it with default settings
const defaultSettings = this.getDefaultSettings()
await writeToFile(defaultSettings, this.settingsFilePath)
console.log('SETTINGS: Returning default settings')
return { type: 'settings', app: 'server', payload: defaultSettings }
}
if (data.autoStart !== undefined) {
await this.updateAutoLaunch(data.autoStart)
}

return { type: 'settings', app: 'server', payload: data }
} catch (err) {
console.error('Error loading settings:', err)
Expand All @@ -92,6 +100,20 @@ class SettingsStore {
}
}

private async updateAutoLaunch(enable: boolean): Promise<void> {
const AutoLaunch = await import('auto-launch')
const autoLaunch = new AutoLaunch.default({
name: 'DeskThing',
path: process.execPath
})

if (enable) {
await autoLaunch.enable()
} else {
await autoLaunch.disable()
}
}

public async saveSettings(settings: socketData | undefined = undefined): Promise<void> {
try {
if (settings) {
Expand Down
10 changes: 7 additions & 3 deletions DeskThingServer/src/main/utils/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,15 @@ class Events extends EventEmitter {
return new Promise((resolve) => {
setImmediate(() => {
// Ensure that two arguments are only emitted at once
this.emit(event, data.join(' '))
if (Array.isArray(data) && data.length > 0 && typeof data[0] === 'string') {
this.emit(event, data.join(' '))
} else {
this.emit(event, data[0])
}

if (event == MESSAGE_TYPES.ERROR) {
if (event === MESSAGE_TYPES.ERROR) {
Logger.error(`[${event}]: ${JSON.stringify(data)}`)
} else if (event == MESSAGE_TYPES.LOGGING) {
} else if (event === MESSAGE_TYPES.LOGGING) {
Logger.info(`[${event}]: ${JSON.stringify(data)}`)
} else {
Logger.debug(`[${event}]: ${JSON.stringify(data)}`)
Expand Down
1 change: 1 addition & 0 deletions DeskThingServer/src/preload/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ declare global {
getClientManifest: () => Promise<any>
setClientManifest: (manifest: any) => Promise<void>
openLogFolder: () => Promise<void>
refreshFirewall: () => Promise<void>
}
api: unknown // Or define `api` more specifically if you have a shape for it
}
Expand Down
Loading

0 comments on commit f4f31b0

Please sign in to comment.