Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions resources/electron/electron-builder.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,12 @@ export default {
executableName: fileName,
...(azureEndpoint && azureCertificateProfileName && azureCodeSigningAccountName
? {
azureSignOptions: {
endpoint: azureEndpoint,
certificateProfileName: azureCertificateProfileName,
codeSigningAccountName: azureCodeSigningAccountName
},
}
azureSignOptions: {
endpoint: azureEndpoint,
certificateProfileName: azureCertificateProfileName,
codeSigningAccountName: azureCodeSigningAccountName,
},
}
: {}),
},
nsis: {
Expand Down
4 changes: 3 additions & 1 deletion resources/electron/electron-plugin/dist/server/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,11 @@ import settingsRoutes from './api/settings.js';
import shellRoutes from './api/shell.js';
import systemRoutes from './api/system.js';
import windowRoutes from './api/window.js';
const API_HOST = '127.0.0.1';
function startAPIServer(randomSecret) {
return __awaiter(this, void 0, void 0, function* () {
const port = yield getPort({
host: API_HOST,
port: portNumbers(4000, 5000),
});
return new Promise((resolve) => {
Expand Down Expand Up @@ -66,7 +68,7 @@ function startAPIServer(randomSecret) {
if (process.env.NODE_ENV === 'development') {
httpServer.use('/api/debug', debugRoutes);
}
const server = httpServer.listen(port, () => {
const server = httpServer.listen(port, API_HOST, () => {
resolve({
server,
port,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,13 @@ function stopProcess(alias) {
}
state.processes[alias].settings.persistent = false;
console.log('Process [' + alias + '] stopping with PID [' + proc.pid + '].');
killSync(proc.pid, 'SIGTERM', true);
proc.kill();
try {
killSync(proc.pid, 'SIGTERM', true);
proc.kill();
}
catch (_a) {
console.log('Process [' + alias + '] already exited — nothing to kill.');
}
}
export function stopAllProcesses() {
for (const alias in state.processes) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ router.post('/create', (req, res) => {
state.activeMenuBar.tray.destroy();
shouldSendCreatedEvent = false;
}
const { width, height, url, label, alwaysOnTop, vibrancy, backgroundColor, transparency, icon, showDockIcon, onlyShowContextMenu, windowPosition, showOnAllWorkspaces, contextMenu, tooltip, resizable, webPreferences, } = req.body;
const { width, height, minWidth, minHeight, maxWidth, maxHeight, url, label, alwaysOnTop, vibrancy, backgroundColor, transparency, icon, showDockIcon, onlyShowContextMenu, windowPosition, showOnAllWorkspaces, contextMenu, tooltip, resizable, webPreferences, } = req.body;
if (onlyShowContextMenu) {
const tray = new Tray(icon || state.icon.replace('icon.png', 'IconTemplate.png'));
tray.setContextMenu(buildMenu(contextMenu));
Expand All @@ -81,6 +81,10 @@ router.post('/create', (req, res) => {
browserWindow: {
width,
height,
minWidth,
minHeight,
maxWidth,
maxHeight,
resizable,
alwaysOnTop,
vibrancy,
Expand Down
28 changes: 11 additions & 17 deletions resources/electron/electron-plugin/dist/server/php.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,20 +39,17 @@ function shouldOptimize() {
return process.env.NODE_ENV !== 'development';
}
function hasNightwatchInstalled(appPath) {
const candidateRoots = [
appPath,
join(appPath, "build", "__nativephp_app_bundle")
];
const candidateRoots = [appPath, join(appPath, 'build', '__nativephp_app_bundle')];
for (const root of candidateRoots) {
if (existsSync(join(root, "vendor", "laravel", "nightwatch"))) {
if (existsSync(join(root, 'vendor', 'laravel', 'nightwatch'))) {
return true;
}
const composerLock = join(root, "composer.lock");
const composerLock = join(root, 'composer.lock');
if (!existsSync(composerLock)) {
continue;
}
try {
if (readFileSync(composerLock, "utf8").includes("\"name\": \"laravel/nightwatch\"")) {
if (readFileSync(composerLock, 'utf8').includes('"name": "laravel/nightwatch"')) {
return true;
}
}
Expand All @@ -65,20 +62,17 @@ function getNightwatchToken(appPath) {
if (process.env.NIGHTWATCH_TOKEN) {
return process.env.NIGHTWATCH_TOKEN;
}
const candidateRoots = [
appPath,
join(appPath, "build", "__nativephp_app_bundle")
];
const candidateRoots = [appPath, join(appPath, 'build', '__nativephp_app_bundle')];
for (const root of candidateRoots) {
const envPath = join(root, ".env");
const envPath = join(root, '.env');
if (!existsSync(envPath)) {
continue;
}
try {
const content = readFileSync(envPath, "utf8");
const content = readFileSync(envPath, 'utf8');
const match = content.match(/^NIGHTWATCH_TOKEN=(.+)$/m);
if (match && match[1]) {
return match[1].replace(/^['"]|['"]$/g, "");
return match[1].replace(/^['"]|['"]$/g, '');
}
}
catch (_a) {
Expand Down Expand Up @@ -248,7 +242,7 @@ function getDefaultEnvironmentVariables(secret, apiPort) {
: join(process.env.APP_PATH, 'extras'),
};
if (secret && apiPort) {
variables.NATIVEPHP_API_URL = `http://localhost:${apiPort}/api/`;
variables.NATIVEPHP_API_URL = `http://127.0.0.1:${apiPort}/api/`;
variables.NATIVEPHP_SECRET = secret;
}
if (runningSecureBuild()) {
Expand Down Expand Up @@ -282,11 +276,11 @@ function serveApp(secret, apiPort, phpIniSettings) {
env.NIGHTWATCH_INGEST_URI = `127.0.0.1:${phpNightWatchPort}`;
}
else if (nightwatchToken) {
console.log("Skipping Nightwatch: package not installed.");
console.log('Skipping Nightwatch: package not installed.');
}
const phpOptions = {
cwd: appPath,
env
env,
};
const store = new Store({
name: 'nativephp',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,8 @@ class Positioner {
y: Math.floor((screenSize.height + screenSize.y) / 2 - windowSize[1] / 2),
},
upperCenter: {
x: Math.floor(
screenSize.x + (screenSize.width / 2 - windowSize[0] / 2),
),
y: Math.floor(
screenSize.y + (screenSize.height - windowSize[1]) / 3,
),
x: Math.floor(screenSize.x + (screenSize.width / 2 - windowSize[0] / 2)),
y: Math.floor(screenSize.y + (screenSize.height - windowSize[1]) / 3),
},
};

Expand Down
5 changes: 4 additions & 1 deletion resources/electron/electron-plugin/src/server/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,11 @@ export interface APIProcess {
port: number;
}

const API_HOST = '127.0.0.1';

async function startAPIServer(randomSecret: string): Promise<APIProcess> {
const port = await getPort({
host: API_HOST,
port: portNumbers(4000, 5000),
});

Expand Down Expand Up @@ -67,7 +70,7 @@ async function startAPIServer(randomSecret: string): Promise<APIProcess> {
httpServer.use('/api/debug', debugRoutes);
}

const server = httpServer.listen(port, () => {
const server = httpServer.listen(port, API_HOST, () => {
resolve({
server,
port,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ function stopProcess(alias) {
// @ts-ignore
killSync(proc.pid, 'SIGTERM', true); // Kill tree
proc.kill(); // Does not work but just in case. (do not put before killSync)
} catch (e) {
} catch {
console.log('Process [' + alias + '] already exited — nothing to kill.');
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ router.post('/open', (req, res) => {
if (state.noFocusOnRestart && window.isVisible()) {
return;
}

window.show();
});

Expand Down
28 changes: 11 additions & 17 deletions resources/electron/electron-plugin/src/server/php.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,24 +47,21 @@ function shouldOptimize() {
}

function hasNightwatchInstalled(appPath: string) {
const candidateRoots = [
appPath,
join(appPath, "build", "__nativephp_app_bundle")
];
const candidateRoots = [appPath, join(appPath, 'build', '__nativephp_app_bundle')];

for (const root of candidateRoots) {
if (existsSync(join(root, "vendor", "laravel", "nightwatch"))) {
if (existsSync(join(root, 'vendor', 'laravel', 'nightwatch'))) {
return true;
}

const composerLock = join(root, "composer.lock");
const composerLock = join(root, 'composer.lock');

if (!existsSync(composerLock)) {
continue;
}

try {
if (readFileSync(composerLock, "utf8").includes("\"name\": \"laravel/nightwatch\"")) {
if (readFileSync(composerLock, 'utf8').includes('"name": "laravel/nightwatch"')) {
return true;
}
} catch {
Expand All @@ -80,24 +77,21 @@ function getNightwatchToken(appPath: string) {
return process.env.NIGHTWATCH_TOKEN;
}

const candidateRoots = [
appPath,
join(appPath, "build", "__nativephp_app_bundle")
];
const candidateRoots = [appPath, join(appPath, 'build', '__nativephp_app_bundle')];

for (const root of candidateRoots) {
const envPath = join(root, ".env");
const envPath = join(root, '.env');

if (!existsSync(envPath)) {
continue;
}

try {
const content = readFileSync(envPath, "utf8");
const content = readFileSync(envPath, 'utf8');
const match = content.match(/^NIGHTWATCH_TOKEN=(.+)$/m);

if (match && match[1]) {
return match[1].replace(/^['"]|['"]$/g, "");
return match[1].replace(/^['"]|['"]$/g, '');
}
} catch {
// ignore and keep looking
Expand Down Expand Up @@ -359,7 +353,7 @@ function getDefaultEnvironmentVariables(secret?: string, apiPort?: number): Envi

// Only if the server has already started
if (secret && apiPort) {
variables.NATIVEPHP_API_URL = `http://localhost:${apiPort}/api/`;
variables.NATIVEPHP_API_URL = `http://127.0.0.1:${apiPort}/api/`;
variables.NATIVEPHP_SECRET = secret;
}

Expand Down Expand Up @@ -402,12 +396,12 @@ async function serveApp(secret, apiPort, phpIniSettings): Promise<ProcessResult>
env.NIGHTWATCH_TOKEN = nightwatchToken;
env.NIGHTWATCH_INGEST_URI = `127.0.0.1:${phpNightWatchPort}`;
} else if (nightwatchToken) {
console.log("Skipping Nightwatch: package not installed.");
console.log('Skipping Nightwatch: package not installed.');
}

const phpOptions = {
cwd: appPath,
env
env,
};

const store = new Store({
Expand Down
10 changes: 9 additions & 1 deletion resources/electron/electron-plugin/tests/api.test.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import axios from 'axios';
import type { AddressInfo } from 'net';
import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest';
import startAPIServer, { APIProcess } from '../src/server/api';

Expand All @@ -21,7 +22,7 @@ describe('API test', () => {
beforeEach(async () => {
vi.resetModules();
apiServer = await startAPIServer('randomSecret');
axios.defaults.baseURL = `http://localhost:${apiServer.port}`;
axios.defaults.baseURL = `http://127.0.0.1:${apiServer.port}`;
});

afterEach(async () => {
Expand All @@ -44,6 +45,13 @@ describe('API test', () => {
nextApiProcess.server.close();
});

it('binds the API server to the loopback interface', async () => {
const address = apiServer.server.address() as AddressInfo;

expect(address.address).toBe('127.0.0.1');
expect(address.address).not.toBe('0.0.0.0');
});

it('protects API endpoints with a secret', async () => {
try {
await axios.get('/api/process');
Expand Down
Loading