From 0c5d744c15c0508cfaad6e76fd7a3d1dcd2d42a1 Mon Sep 17 00:00:00 2001 From: Sylvain Marty Date: Tue, 21 May 2019 01:37:13 +0200 Subject: [PATCH 1/3] Trying a fix for Electron updater --- src/main/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/index.js b/src/main/index.js index 561cded..2d77e9e 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -30,7 +30,7 @@ const winURL = process.env.NODE_ENV === 'development' : `file://${__dirname}/index.html` function createWindow () { - if (process.env.NODE_ENV === 'production') autoUpdater.checkForUpdates() + if (process.env.NODE_ENV === 'production') autoUpdater.checkForUpdatesAndNotify() global.printrz = { api: new Api() From a5689bce863b6cc735f2a33814bb6915a32c0ece Mon Sep 17 00:00:00 2001 From: Sylvain Marty Date: Tue, 21 May 2019 01:39:03 +0200 Subject: [PATCH 2/3] Implementing port update and certificate generation --- package.json | 1 + src/main/api.js | 57 +++++---- src/main/certificate.js | 87 +++++++++++++ src/main/configuration.js | 62 +++++++++ src/main/index.js | 7 +- src/renderer/components/Home.vue | 6 +- src/renderer/components/Settings.vue | 185 ++++++++++++++++++++++++++- src/renderer/main.js | 11 +- src/renderer/plugins/http.js | 9 ++ yarn.lock | 5 + 10 files changed, 391 insertions(+), 39 deletions(-) create mode 100644 src/main/certificate.js create mode 100644 src/main/configuration.js create mode 100644 src/renderer/plugins/http.js diff --git a/package.json b/package.json index 3ddba55..66755c3 100644 --- a/package.json +++ b/package.json @@ -71,6 +71,7 @@ "ip": "^1.1.5", "material-icons": "^0.3.1", "morgan": "^1.9.1", + "node-forge": "^0.8.2", "printer": "^0.2.2", "vue": "^2.5.16", "vue-electron": "^1.0.6", diff --git a/src/main/api.js b/src/main/api.js index 78bbd7c..7100e19 100644 --- a/src/main/api.js +++ b/src/main/api.js @@ -1,11 +1,13 @@ -const express = require('express') -const cors = require('cors') -const bodyParser = require('body-parser') -const logger = require('morgan') -const printer = require('printer') -const port = 5000 +import { app } from 'electron' +import express from 'express' +import cors from 'cors' +import bodyParser from 'body-parser' +import logger from 'morgan' +import printer from 'printer' +import https from 'https' +import { getCertificateFiles } from './certificate' -export default function (callback) { +export default function ({ port }) { const server = express() server.use(cors()) server.use(bodyParser.json()) @@ -48,26 +50,31 @@ export default function (callback) { } }) }) - /* const instance = */server.listen(port, () => { + + let isHttps = false + let callback = () => { console.log(`Print server listening on port ${port}!`) - if (callback) { - callback() - } - }) + } + try { + console.log('Starting server on HTTPS...') + let certFiles = getCertificateFiles(app.getPath('userData'), true) + https + .createServer( + { + key: certFiles.privateKey, + cert: certFiles.certificate + }, + server + ) + .listen(port, callback) + isHttps = true + } catch (e) { + console.log('Cannot run with HTTPS, fallback on HTTP...') + server.listen(port, callback) + } return { - // TODO: fix that stuff - /* stopServer () { - return new Promise((resolve, reject) => { - try { - instance.close(() => { - console.log(`Print server stopped!`) - resolve() - }) - } catch (e) { - reject(e) - } - }) - } */ + isHttps, + port } } diff --git a/src/main/certificate.js b/src/main/certificate.js new file mode 100644 index 0000000..192a15c --- /dev/null +++ b/src/main/certificate.js @@ -0,0 +1,87 @@ +import fs from 'fs' +import path from 'path' +import forge from 'node-forge' +import { promisify } from 'util' +const readFileAsync = promisify(fs.readFile) +const writeFileAsync = promisify(fs.writeFile) +forge.options.usePureJavaScript = true + +/** + * Get certificate files paths and names + * @param {String} certsPath The certificate's files main location + */ +let getPaths = function (certsPath) { + return { + key: path.join(certsPath, 'key.pem'), + cert: path.join(certsPath, 'cert.pem') + } +} + +/** + * Get certificate files content + * @param {String} certsPath The certificate's files main location + * @param {*} sync If true, load the file synchronously (default false) + */ +let getCertificateFiles = function (certsPath, sync = false) { + let paths = getPaths(certsPath) + + if (sync) { + return { + privateKey: fs.readFileSync(paths.key), + certificate: fs.readFileSync(paths.cert) + } + } + + return Promise.all([ + readFileAsync(paths.key), + readFileAsync(paths.cert) + ]).then(results => ({ + privateKey: results[0], + certificate: results[1] + })) +} + +/** + * Generate new SSL certificate files + * @param {String} certsPath The certificate's files main location + * @param {Object} object The certificate attributes + */ +let generateCertificateFiles = function (certsPath, { organizationName, countryName, stateOrProvinceName, localityName }) { + let paths = getPaths(certsPath) + let pki = forge.pki + let keys = pki.rsa.generateKeyPair(2048) + let cert = pki.createCertificate() + let attributes = [ + {name: 'commonName', value: organizationName}, + {name: 'countryName', value: countryName}, + {shortName: 'ST', value: stateOrProvinceName}, + {name: 'localityName', value: localityName}, + {name: 'organizationName', value: organizationName}, + {shortName: 'OU', value: organizationName} + ] + + cert.publicKey = keys.publicKey + cert.serialNumber = '01' + cert.validity.notBefore = new Date() + cert.validity.notAfter = new Date() + cert.validity.notAfter.setFullYear(cert.validity.notBefore.getFullYear() + 10) + cert.setSubject(attributes) + cert.setIssuer(attributes) + cert.sign(keys.privateKey) + let privateKey = pki.privateKeyToPem(keys.privateKey) + let certificate = pki.certificateToPem(cert) + + return Promise.all([ + writeFileAsync(paths.key, privateKey), + writeFileAsync(paths.cert, certificate) + ]).then(() => ({ + privateKey, + certificate + })) +} + +export { + getPaths, + getCertificateFiles, + generateCertificateFiles +} diff --git a/src/main/configuration.js b/src/main/configuration.js new file mode 100644 index 0000000..23f8de4 --- /dev/null +++ b/src/main/configuration.js @@ -0,0 +1,62 @@ +import fs from 'fs' +import path from 'path' +import { promisify } from 'util' +const readFileAsync = promisify(fs.readFile) +const writeFileAsync = promisify(fs.writeFile) +const DEFAULT_CONFIGURATION = { + port: 5000 +} + +/** + * Get the path to the configuration file + * @param {String} configPath The path to root directory of config.json + */ +let getFilePath = function (configPath) { + return path.join(configPath, 'config.json') +} + +/** + * Get the configuration file content (parsed to object) + * @param {String} configPath The path to root directory of config.json + * @param {Boolean} sync If true, load the file synchronously (default false) + */ +let getConfiguration = function (configPath, sync = false) { + let filePath = getFilePath(configPath) + + if (sync) { + try { + return JSON.parse(fs.readFileSync(filePath)) + } catch (e) { + return DEFAULT_CONFIGURATION + } + } + + return readFileAsync(filePath) + .then(content => JSON.parse(content)) + .catch(() => DEFAULT_CONFIGURATION) +} + +/** + * Update the configuration file with full/partial configuration + * @param {String} configPath The path to root directory of config.json + * @param {Object} configuration A partial object which will be stored in the config.json file + */ +let setConfiguration = function (configPath, configuration) { + let filePath = getFilePath(configPath) + return getConfiguration(configPath) + .then(content => { + return writeFileAsync( + filePath, + JSON.stringify( + Object.assign({}, content, configuration), + null, 4 + ) + ) + }) +} + +export { + getFilePath, + getConfiguration, + setConfiguration +} diff --git a/src/main/index.js b/src/main/index.js index 2d77e9e..0987598 100644 --- a/src/main/index.js +++ b/src/main/index.js @@ -4,6 +4,9 @@ import { app, BrowserWindow } from 'electron' import { autoUpdater } from 'electron-updater' import log from 'electron-log' import Api from './api' +import { getConfiguration } from './configuration' + +app.commandLine.appendSwitch('ignore-certificate-errors') /** * Auto Updater @@ -32,8 +35,10 @@ const winURL = process.env.NODE_ENV === 'development' function createWindow () { if (process.env.NODE_ENV === 'production') autoUpdater.checkForUpdatesAndNotify() + let conf = getConfiguration(app.getPath('userData'), true) global.printrz = { - api: new Api() + configuration: conf, + api: new Api(conf) } /** diff --git a/src/renderer/components/Home.vue b/src/renderer/components/Home.vue index 79762f6..9bd45c1 100644 --- a/src/renderer/components/Home.vue +++ b/src/renderer/components/Home.vue @@ -53,9 +53,7 @@ \ No newline at end of file + + + \ No newline at end of file diff --git a/src/renderer/main.js b/src/renderer/main.js index 0c4fc5f..0246164 100644 --- a/src/renderer/main.js +++ b/src/renderer/main.js @@ -1,12 +1,19 @@ +import { remote } from 'electron' import Vue from 'vue' -import axios from 'axios' import App from './App' import router from './router' +import http from './plugins/http' + +const api = remote.getGlobal('printrz').api if (!process.env.IS_WEB) Vue.use(require('vue-electron')) -Vue.http = Vue.prototype.$http = axios Vue.config.productionTip = false +Vue.use(http, { + protocol: api.isHttps ? 'https' : 'http', + host: 'localhost', + port: api.port +}) /* eslint-disable no-new */ new Vue({ diff --git a/src/renderer/plugins/http.js b/src/renderer/plugins/http.js new file mode 100644 index 0000000..facb71d --- /dev/null +++ b/src/renderer/plugins/http.js @@ -0,0 +1,9 @@ +import axios from 'axios' + +export default { + install: function (Vue, { protocol, host, port }) { + Vue.http = Vue.prototype.$http = axios.create({ + baseURL: `${protocol}://${host}:${port}` + }) + } +} diff --git a/yarn.lock b/yarn.lock index 3f4de68..67ef7c7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -7311,6 +7311,11 @@ node-forge@0.7.5: resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.7.5.tgz#6c152c345ce11c52f465c2abd957e8639cd674df" integrity sha512-MmbQJ2MTESTjt3Gi/3yG1wGpIMhUfcIypUCGtTizFR9IiccFwxSpfp0vtIZlkFclEqERemxfnSdZEMR9VqqEFQ== +node-forge@^0.8.2: + version "0.8.2" + resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-0.8.2.tgz#b4bcc59fb12ce77a8825fc6a783dfe3182499c5a" + integrity sha512-mXQ9GBq1N3uDCyV1pdSzgIguwgtVpM7f5/5J4ipz12PKWElmPpVWLDuWl8iXmhysr21+WmX/OJ5UKx82wjomgg== + node-gyp@^3.8.0: version "3.8.0" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.8.0.tgz#540304261c330e80d0d5edce253a68cb3964218c" From ffb6bee319d5f534139c3bfd3f29a823985724de Mon Sep 17 00:00:00 2001 From: Sylvain Marty Date: Tue, 21 May 2019 08:38:03 +0200 Subject: [PATCH 3/3] Fixing non-breacking space --- src/renderer/components/Settings.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/renderer/components/Settings.vue b/src/renderer/components/Settings.vue index 666ed04..5756cd9 100644 --- a/src/renderer/components/Settings.vue +++ b/src/renderer/components/Settings.vue @@ -8,7 +8,7 @@
- {{ ip }}  content_copy + {{ ip }}  content_copy
Local IP