Desktop app (#745)

* Set up electron app

* Update dependencies

* Update package.json

* Added https support

* Add support for Ledger

* Updated certs

* Added auto updates messages

* Update auto-updater method

* Update package.json

* Added build resources

* Update preload

* Update Ledger method on mac

* Update build

* Merge with develop

* Added support for Portis

* Fix electron error and updater

* Update auto updater

* Fix dependencies

* Merge with develop

* Change auto update functionality

* Edit package.json and added github actions

* Updated github actions

* Fixed Torus + Update github actions

* Updated release.yml

* Try only ubuntu

* Update package.json

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* Updated safe-contracts

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* v1.9.6

* Updated deploy branch

* Updated script

Co-authored-by: Mati Dastugue <matias.dastugue@mercadolibre.com>
This commit is contained in:
Mati Dastugue 2020-04-24 11:10:37 -03:00 committed by GitHub
parent 5cbb8f52ac
commit c57885d489
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 3511 additions and 667 deletions

View File

@ -0,0 +1,55 @@
name: Build/release
# this will help you specify where to run
on:
push:
branches:
# this will run on the specified branch
- feature/desktop-app
env:
REACT_APP_BLOCKNATIVE_KEY: ${{ secrets.REACT_APP_BLOCKNATIVE_KEY }}
REACT_APP_FORTMATIC_KEY: ${{ secrets.REACT_APP_FORTMATIC_KEY }}
REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET: ${{ secrets.REACT_APP_GOOGLE_ANALYTICS_ID_MAINNET }}
REACT_APP_INFURA_TOKEN: ${{ secrets.REACT_APP_INFURA_TOKEN }}
REACT_APP_PORTIS_ID: ${{ secrets.REACT_APP_PORTIS_ID }}
jobs:
release:
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [macos-latest, ubuntu-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v1
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 10.16
- name: Build/release Electron app
env:
# macOS notarization API key
APPLEID: ${{ secrets.APPLE_ID }}
APPLEIDPASS: ${{ secrets.APPLE_ID_PASS }}
uses: samuelmeuli/action-electron-builder@v1
with:
#Build scipt
build_script_name: build-desktop
# GitHub token, automatically provided to the action
# (No need to define this secret in the repo settings)
github_token: ${{ secrets.github_token }}
# macOS code signing certificate
mac_certs: ${{ secrets.MAC_CERTS }}
mac_certs_password: ${{ secrets.MAC_CERTS_PASSWORD }}
# If the commit is tagged with a version (e.g. "v1.0.0"),
# release the app after building
release: ${{ startsWith(github.ref, 'refs/tags/v') }}

View File

@ -1,11 +1,11 @@
name: Build/release
name: Build/Release Desktop app
# this will help you specify where to run
on:
push:
branches:
# this will run on the specified branch
- feature/desktop-app
- master
env:
REACT_APP_BLOCKNATIVE_KEY: ${{ secrets.REACT_APP_BLOCKNATIVE_KEY }}
@ -19,19 +19,33 @@ jobs:
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
max-parallel: 15
matrix:
os: [macos-latest, ubuntu-latest, windows-latest]
os: [macos-latest, windows-latest, ubuntu-latest]
steps:
- name: Check out Git repository
uses: actions/checkout@v1
uses: actions/checkout@v2
- name: Install Node.js, NPM and Yarn
uses: actions/setup-node@v1
with:
node-version: 10.16
- name: Build/release Electron app
- name: Patch node gyp on windows to support Visual Studio 2019
if: startsWith(matrix.os, 'windows')
shell: powershell
run: |
yarn global add --production windows-build-tools --vs2015 --msvs_version=2015
- name: Install node-gyp
if: startsWith(matrix.os, 'windows')
shell: powershell
run: |
yarn global add node-gyp
yarn config set node_gyp "$_\node_modules\node-gyp\bin\node-gyp.js"
- name: Build/Release Desktop App
env:
# macOS notarization API key
APPLEID: ${{ secrets.APPLE_ID }}

6
.gitignore vendored
View File

@ -1,9 +1,11 @@
node_modules/
build_webpack/
.DS_Store
build/
./build
yarn-error.log
.env*
.idea/
dist
electron-builder.yml
.yalc/
yalc.lock
yalc.lock

View File

@ -52,9 +52,11 @@ function ensureSlash(path, needsSlash) {
// single-page apps that may serve index.html for nested URLs like /todos/42.
// We can't use a relative path in HTML because we don't want to load something
// like /todos/42/static/js/bundle.7289d.js. We have to know the root.
const buildDesktop = process.env.BUILD_FOR_DESKTOP
const homepagePath = require(paths.appPackageJson).homepage
// var homepagePathname = homepagePath ? url.parse(homepagePath).pathname : '/';
const homepagePathname = "/app/"
const homepagePathname = buildDesktop === 'true' ? "./" : "/app/"
// Webpack uses `publicPath` to determine where the app is being served from.
// It requires a trailing slash, or the file assets will get an incorrect path.
const publicPath = ensureSlash(homepagePathname, true)

View File

@ -1,6 +1,6 @@
{
"name": "safe-react",
"version": "1.9.5",
"version": "1.9.6",
"description": "Allowing crypto users manage funds in a safer way",
"homepage": "https://github.com/gnosis/safe-react#readme",
"bugs": {
@ -8,16 +8,24 @@
},
"repository": {
"type": "git",
"url": "https://github.com/gnosis/safe-react"
"url": "https://github.com/gnosis/safe-react.git"
},
"license": "MIT",
"author": "Gnosis Team",
"directories": {
"test": "test"
"author": {
"name": "Gnosis Team",
"email": "safe@gnosis.io"
},
"main": "public/electron.js",
"postinstall": "electron-builder install-app-deps",
"scripts": {
"build": "REACT_APP_APP_VERSION=$npm_package_version node scripts/build.js",
"build-mainnet": "REACT_APP_NETWORK=mainnet yarn build",
"build": "cross-env REACT_APP_APP_VERSION=$npm_package_version node scripts/build.js",
"electron-build": "electron-builder --mac --windows --linux",
"postinstall": "electron-builder install-app-deps",
"release": "electron-builder --mac --linux --windows -p always",
"electron-dev": "concurrently \"BROWSER=none yarn start\" \"wait-on http://localhost:3000 && electron .\"",
"preelectron-pack": "yarn build",
"build-mainnet": "cross-env REACT_APP_NETWORK=mainnet yarn build",
"build-desktop": "cross-env BUILD_FOR_DESKTOP=true yarn build-mainnet",
"flow": "flow",
"format:staged": "lint-staged",
"lint:check": "eslint './src/**/*.{js,jsx}'",
@ -40,9 +48,96 @@
"prettier --write"
]
},
"productName": "Safe Electron",
"build": {
"appId": "io.gnosis.safe.macos",
"afterSign": "scripts/notarize.js",
"productName": "Safe Electron",
"asar": true,
"publish": [
{
"provider": "github",
"owner": "gnosis",
"repo": "safe-react"
}
],
"dmg": {
"sign": false,
"contents": [
{
"x": 110,
"y": 150
},
{
"x": 240,
"y": 150,
"type": "link",
"path": "/Applications"
}
]
},
"files": [
"**/*",
"!src${/*}",
"!config${/*}",
"!contracts${/*}",
"!migrations${/*}",
"!flow-typed${/*}",
"!apps${/*}",
"!build${/*}",
"!out${/*}",
"!.editorconfig",
"!.gitignore",
"!README.md",
"!yarn-error.log",
"!yarn.lock"
],
"directories": {
"buildResources": "public/build"
},
"mac": {
"category": "public.app-category.productivity",
"hardenedRuntime": true,
"entitlements": "public/build/entitlements.mac.plist",
"gatekeeperAssess": false,
"entitlementsInherit": "public/build/entitlements.mac.plist",
"target": [
"dmg",
"zip"
],
"publish": [
{
"provider": "github",
"owner": "gnosis",
"repo": "safe-react"
}
]
},
"nsis": {
"deleteAppDataOnUninstall": true
},
"linux": {
"target": [
"AppImage",
"deb",
"zip"
],
"icon": "./public/build/safe.png"
},
"win": {
"target": [
"nsis"
],
"icon": "public/build/icon.ico"
}
},
"resolutions": {
"node-gyp": "^5.1.0"
},
"dependencies": {
"@gnosis.pm/safe-contracts": "1.1.1-dev.1",
"@gnosis.pm/safe-contracts": "1.1.1-dev.2",
"@gnosis.pm/util-contracts": "2.0.6",
"@ledgerhq/hw-transport-node-hid": "5.12.0",
"@gnosis.pm/safe-react-components": "https://github.com/gnosis/safe-react-components.git#71e6fed",
"@material-ui/core": "4.9.10",
"@material-ui/icons": "4.9.1",
@ -55,18 +150,26 @@
"bignumber.js": "9.0.0",
"bnc-onboard": "1.7.6",
"connected-react-router": "6.8.0",
"cross-env": "^7.0.2",
"currency-flags": "^2.1.1",
"date-fns": "2.12.0",
"dotenv": "^8.2.0",
"electron-is-dev": "^1.1.0",
"electron-log": "^4.1.1",
"electron-updater": "4.2.0",
"ethereum-ens": "0.8.0",
"express": "^4.17.1",
"final-form": "4.19.1",
"history": "4.10.1",
"immortal-db": "^1.0.2",
"immutable": "^4.0.0-rc.9",
"install": "^0.13.0",
"js-cookie": "^2.2.1",
"lint-staged": "10.1.3",
"material-ui-search-bar": "^1.0.0-beta.13",
"notistack": "https://github.com/gnosis/notistack.git#v0.9.4",
"npm": "^6.14.4",
"open": "^7.0.3",
"optimize-css-assets-webpack-plugin": "5.0.3",
"polished": "3.5.1",
"qrcode.react": "1.0.0",
@ -89,6 +192,7 @@
"reselect": "^4.0.0",
"semver": "7.3.2",
"styled-components": "^5.0.1",
"wait-on": "^4.0.1",
"web3": "1.2.6"
},
"devDependencies": {
@ -127,9 +231,13 @@
"babel-plugin-transform-es3-property-literals": "^6.22.0",
"babel-polyfill": "^6.26.0",
"classnames": "^2.2.6",
"concurrently": "4.1.2",
"css-loader": "3.5.2",
"detect-port": "^1.3.0",
"dotenv-expand": "^5.1.0",
"electron": "7.1.8",
"electron-builder": "22.2.0",
"electron-notarize": "^0.2.1",
"eslint": "^6.8.0",
"eslint-config-prettier": "6.10.1",
"eslint-plugin-flowtype": "4.7.0",

View File

@ -0,0 +1,69 @@
const os = require('os');
const fetch = require('node-fetch');
const { dialog, app } = require('electron');
const log = require('electron-log');
const isDev = require("electron-is-dev");
const { autoUpdater } = require("electron-updater");
// This logging setup is not required for auto-updates to work,
// but it sure makes debugging easier :)
//-------------------------------------------------------------------
autoUpdater.autoDownload = false
autoUpdater.logger = log;
autoUpdater.logger.transports.file.level = 'info';
log.info('App starting...');
let initialized = false;
let downloadProgress = 0;
function init(mainWindow) {
if(initialized || isDev) return;
initialized = true;
autoUpdater.on('error', (error) => {
dialog.showErrorBox('Error: ', error == null ? "unknown" : (error.stack || error).toString());
});
autoUpdater.on('update-available', () => {
dialog.showMessageBox({
type: 'info',
title: 'Found Updates',
message: 'There is a newer version of this app available. Do you want to update now?',
buttons: ['Yes', 'Remind me later'],
cancelId:1,
}).then(result => {
if(result.response === 0){
autoUpdater.downloadUpdate();
}
});
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
autoUpdater.logger.info("Update Downloaded...");
dialog.showMessageBox({
title: 'Install Updates',
message: process.platform === 'win32' ? releaseNotes : releaseName,
detail: 'A new version has been downloaded. Restart the application to apply the updates.',
buttons: ['Restart', 'Cancel'],
cancelId:1,
}).then(result => {
if(result.response === 0){
autoUpdater.quitAndInstall();
}
});
});
});
autoUpdater.on("download-progress", (d) => {
downloadProgress = d.percent;
autoUpdater.logger.info(downloadProgress);
});
autoUpdater.checkForUpdates();
}
module.exports = {
init,
};

BIN
public/build/all-certs.p12 Normal file

Binary file not shown.

BIN
public/build/background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 83 KiB

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.network.client</key>
<true/>
<key>com.apple.security.network.server</key>
<true/>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.device.camera</key>
<true/>
<key>com.apple.security.device.microphone</key>
<true/>
<key>com.apple.security.cs.allow-dyld-environment-variables</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist>

BIN
public/build/icon.icns Normal file

Binary file not shown.

BIN
public/build/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
public/build/safe.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

162
public/electron.js Normal file
View File

@ -0,0 +1,162 @@
const electron = require("electron");
const express = require('express');
const open = require('open');
const log = require('electron-log');
const fs = require('fs');
const dialog = electron.dialog;
const Menu = electron.Menu;
const https = require('https');
const autoUpdater = require('./auto-updater');
const url = require('url');
const app = electron.app;
const session = electron.session;
const BrowserWindow = electron.BrowserWindow;
const path = require("path");
const isDev = require("electron-is-dev");
const options = {
key: fs.readFileSync(path.join(__dirname, './ssl/server.key')),
cert: fs.readFileSync(path.join(__dirname, './ssl/server.crt')),
ca: fs.readFileSync(path.join(__dirname, './ssl/rootCA.crt'))
};
const PORT = 5000;
const createServer = () => {
const app = express();
const staticRoute = path.join(__dirname, '../build_webpack');
app.use(express.static(staticRoute));
https.createServer(options, app).listen(PORT);
}
let mainWindow;
function getOpenedWindow(url,options) {
let display = electron.screen.getPrimaryDisplay();
let width = display.bounds.width;
let height = display.bounds.height;
// filter all requests to trezor-bridge and change origin to make it work
const filter = {
urls: ['http://127.0.0.1:21325/*']
};
options.webPreferences.affinity = 'main-window';
if(url.includes('about:blank')){
/*
session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
details.requestHeaders['Origin'] = 'https://electron.trezor.io';
callback({cancel: false, requestHeaders: details.requestHeaders});
});
*/
}
if(url.includes('wallet.portis') || url.includes('about:blank') || url.includes('app.tor.us')){
const win = new BrowserWindow({
width:300,
height:700,
x: width - 1300,
parent:mainWindow,
y: height - 200,
webContents: options.webContents, // use existing webContents if provided
fullscreen: false,
show: false,
});
win.once('ready-to-show', () => win.show());
if(!options.webPreferences){
win.loadURL(url);
}
return win
}
return null;
}
function createWindow() {
mainWindow = new BrowserWindow({
show: false,
width: 1024,
height: 768,
webPreferences: {
preload: path.join(__dirname, '../scripts/preload.js'),
allowRunningInsecureContent: true,
nativeWindowOpen: true, // need to be set in order to display modal
},
icon: path.join(__dirname, './build/safe.png'),
});
mainWindow.once('ready-to-show', () => {
mainWindow.show();
});
mainWindow.loadURL(
isDev
? "http://localhost:3000"
: `https://localhost:${PORT}`
)
if (isDev) {
// Open the DevTools.
mainWindow.webContents.openDevTools();
//BrowserWindow.addDevToolsExtension('<location to your react chrome extension>');
}
mainWindow.setMenu(null);
mainWindow.setMenuBarVisibility(false);
mainWindow.webContents.on('new-window', function(event, url, frameName, disposition, options){
event.preventDefault();
const win = getOpenedWindow(url,options);
if(win){
win.once('ready-to-show', () => win.show());
if(!options.webPreferences){
win.loadURL(url);
}
event.newGuest = win
} else open(url);
});
mainWindow.webContents.on('did-finish-load', () => {
autoUpdater.init(mainWindow);
});
mainWindow.webContents.on('crashed', () => {
log.info('App Crashed');
mainWindow.reload();
});
mainWindow.on("closed", () => (mainWindow = null));
}
app.userAgentFallback = process.platform ==='win32' ?
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.100 Safari/537.36' :
'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) old-airport-include/1.0.0 Chrome Electron/7.1.7 Safari/537.36';
app.commandLine.appendSwitch('ignore-certificate-errors');
app.on("ready", () =>{
// Hide the menu
//Menu.setApplicationMenu(null);
if(!isDev) createServer();
createWindow();
});
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
}
});
app.on("activate", () => {
if (mainWindow === null) {
createWindow();
}
});

20
public/ssl/client.crt Normal file
View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDTzCCAjcCFA3n/7f/k+b9g/7W6zodg+u2qC3BMA0GCSqGSIb3DQEBCwUAMGQx
CzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdHZXJtYW55MREwDwYDVQQHDAhXYWxsZG9y
ZjEPMA0GA1UECgwGU0FQIFNFMQ4wDAYDVQQLDAVUb29sczEPMA0GA1UEAwwGcm9v
dENBMB4XDTIwMDMyNzIxMTkxNFoXDTIxMDgwOTIxMTkxNFowZDELMAkGA1UEBhMC
REUxEDAOBgNVBAgMB0dlcm1hbnkxETAPBgNVBAcMCFdhbGxkb3JmMQ8wDQYDVQQK
DAZTQVAgU0UxDjAMBgNVBAsMBVRvb2xzMQ8wDQYDVQQDDAZjbGllbnQwggEiMA0G
CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCZ7hsC/0FOfOUUyefqhFvmiYJoqMSi
8/vvjJKn+TCXhlfX/BLxBtJN8BlFNDux+qPlPhElbCg0bldeBGkZNgD7Jt6Fjpkd
SqqoDIcfl+oxAks76Qi5hh2FKHSOp3BmHgVuur+cbzOd8J+NsskGYay32mAHLrq8
ixPLUtkOO9W2PSKm9KQEwOdYV9R/dStvZDA5dEVEDGv3MIBgRVzyu8gGwMfjzci1
wgwU5Eb2r2b7Vs19nAoLQwelBf4bL5Z5b2KjfW1HPhmtM1eBaf+3bMscnemAgY8I
0ZHMS0XjORLvSBKZ73Q1K9lv6dc45fQA6g3KnVvFSB0nfqbhw7vuDEXrAgMBAAEw
DQYJKoZIhvcNAQELBQADggEBAAzKry8DXN6tlIE5ZRp9z/MdT8bOSwNQM9H/E1Rn
50fP5C3m5IZioYdsfQtDvEC2bHHIYyWvqL6AAWVOzA8Pvnw1J32Sq3Tz5EwH0B5p
wRVxB2GEe7WqSQV88fd2l35/5vcpoe5A444n6qb8ZaqzdBYXgyUPyVAbzcySKEm/
b1HuV8dhlOWZcwgGAdgf/yBhu8WN1Mau6zTAFK2osKUQM2TeXCDKX6tDAHryD6jA
MP/med+RSLJyyL5OYBl1P/gqSstH0HnpkpeYslaZpXncT2V2PHTwXOs2ywOESil6
yEi9KcsPe87hJ5aMJ0iw/A8AkDBnSzvx2LoYtgLxWl/+4xw=
-----END CERTIFICATE-----

17
public/ssl/client.csr Normal file
View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICqTCCAZECAQAwZDELMAkGA1UEBhMCREUxEDAOBgNVBAgMB0dlcm1hbnkxETAP
BgNVBAcMCFdhbGxkb3JmMQ8wDQYDVQQKDAZTQVAgU0UxDjAMBgNVBAsMBVRvb2xz
MQ8wDQYDVQQDDAZjbGllbnQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
AQCZ7hsC/0FOfOUUyefqhFvmiYJoqMSi8/vvjJKn+TCXhlfX/BLxBtJN8BlFNDux
+qPlPhElbCg0bldeBGkZNgD7Jt6FjpkdSqqoDIcfl+oxAks76Qi5hh2FKHSOp3Bm
HgVuur+cbzOd8J+NsskGYay32mAHLrq8ixPLUtkOO9W2PSKm9KQEwOdYV9R/dStv
ZDA5dEVEDGv3MIBgRVzyu8gGwMfjzci1wgwU5Eb2r2b7Vs19nAoLQwelBf4bL5Z5
b2KjfW1HPhmtM1eBaf+3bMscnemAgY8I0ZHMS0XjORLvSBKZ73Q1K9lv6dc45fQA
6g3KnVvFSB0nfqbhw7vuDEXrAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEAMQNR
9TrgG1Re1z2nmxQ2lWPfpdx5wTFc2SibJhMGTahEhAW6XJEtYpTPE+S2LEIybr9k
Ya+Pg/Q6pE2MjCDMOSkmfXVcyu/Fw+Ek1anNQ1IDS68vVA3lUNpXYHPffZOTdlj6
15n7GMUdSISLk8jZOLGli26PLQimSzHeLUjHwFaS6fs5dXrASdDEAq+GfjXw+R83
Lh6ENb9ojdtnHhEspWsiuyJVT4GgV2U1q9m+ljZJe8fBgQP3exxVZXgnAeogpy4r
+pTjJIRuaxr3xnd/oYQDCaKpXptEuHQ5caQzFmmUM94sAZkQJQn5VVjSCfDv2ZHm
Rp+QdXH8iMjiaxKUaQ==
-----END CERTIFICATE REQUEST-----

27
public/ssl/client.key Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAme4bAv9BTnzlFMnn6oRb5omCaKjEovP774ySp/kwl4ZX1/wS
8QbSTfAZRTQ7sfqj5T4RJWwoNG5XXgRpGTYA+ybehY6ZHUqqqAyHH5fqMQJLO+kI
uYYdhSh0jqdwZh4Fbrq/nG8znfCfjbLJBmGst9pgBy66vIsTy1LZDjvVtj0ipvSk
BMDnWFfUf3Urb2QwOXRFRAxr9zCAYEVc8rvIBsDH483ItcIMFORG9q9m+1bNfZwK
C0MHpQX+Gy+WeW9io31tRz4ZrTNXgWn/t2zLHJ3pgIGPCNGRzEtF4zkS70gSme90
NSvZb+nXOOX0AOoNyp1bxUgdJ36m4cO77gxF6wIDAQABAoIBAQCEQ+Vv8Ncz0vug
nlEp4St6b2Pf/ExiXNV5I8gMj4FiYexvSUkZVCw3Df0YyuYUa3KTE372MfZl/v4R
aibIo++53s9L4ZjNY5A6L/GXgxiXngn5Y6a8i3IoLffhcByTkm5GlC77A05OAymG
Pz6eviUEIZ9r7IpGYhbTGdAqe92J5a72yaGK7+xzA/srX1a8C1qVqsoVBT/js99m
kNGZDbpjNLZhXAaze51+Z4ehwVDjJXHgxiCRvoZprxo49DTe/xKef5k1p8rEcv78
b56B5fYXOnIa2VavEJmEcuaX7uEAW2LT5/hRck/1ekhUBkhJ1BjzgYXqrbX9BiMO
wiSjn9pRAoGBAMtg9ewPESMLdKvxAQ9O6DEoRlN1KqHjwkoDZXM9Hw1dDWtxDsuC
MwvlzQEj0EVF1N5FedQVuaFVB6Bcq2tIcqvtYOBsflkF01Fe6CSgrqwmWps2tw4p
3TbFPNtXlQwUN0CcOzlCimo5dWoa5GT5VAEjXJBy1qmlZunbPlYJBf+pAoGBAMHB
2mdK5SKjvduEm+65W4VyhY1S40a8sGI9LcbCnMN1sZcOII0I/1CVsvJMZDj6XVbA
/dT76OkrL8uk20oYImNpfMSejiBUB4nLbhcI665jVUd9mG+H0v+wT9L6Nh9cvA8U
QNHHPGkzBFOqzXk59p8cFWoIIY5xzcPiydh7jyVzAoGBALwPn7e1wvnt6Ofphjpa
k7iI7mbT7CUgz5LTCyeBeEpKJlOYir7CWWOCDowkSr0TsqAKDHqB0FIPp2qw5k3h
AzBZ44ACst6s1Vfj87OS5ZIIMTZfZOvy6DxyLDEDDq7JrsHO9bCgCA/rq9f+n/2C
1BvtT/W+SyM58C0E7+Jsm6BpAoGBAJrP1T3q7aH7ytr23dCkcafylRsSO15trVER
KN5C6RaTl03mj8OgiL9OnShUOU/9W07R7P6cOMD1LL89/aj6F5/uzS4csdrKySsk
S9ZD3mv8GkuA4qdakxCRQ3aDTXNJmUlDGXeEBZTYmoBvXLWbxp3ixolt7cHu1EXL
kxNRxlJZAoGAO/Qzs10/joY5R7jadZdclVfleuD0Y5HmpEr2WgXvVwzB3QJqHd2i
lovuNtDpUal5ncDzDKdHacoED5gYncDIT6Quair3VfHsm3LlQWiZT86bQUWRBD+J
z/4ppzGkzePS4Rf01Cjb7RwlQ7uDCaVyPjvCbAVaPBYQVr3FvaYLJbM=
-----END RSA PRIVATE KEY-----

BIN
public/ssl/client.p12 Normal file

Binary file not shown.

22
public/ssl/rootCA.crt Normal file
View File

@ -0,0 +1,22 @@
-----BEGIN CERTIFICATE-----
MIIDqTCCApGgAwIBAgIUdULIRijfukG4cY7OZiPC02tL2WYwDQYJKoZIhvcNAQEL
BQAwZDELMAkGA1UEBhMCREUxEDAOBgNVBAgMB0dlcm1hbnkxETAPBgNVBAcMCFdh
bGxkb3JmMQ8wDQYDVQQKDAZTQVAgU0UxDjAMBgNVBAsMBVRvb2xzMQ8wDQYDVQQD
DAZyb290Q0EwHhcNMjAwMzI3MjExOTE0WhcNMjMwMTE1MjExOTE0WjBkMQswCQYD
VQQGEwJERTEQMA4GA1UECAwHR2VybWFueTERMA8GA1UEBwwIV2FsbGRvcmYxDzAN
BgNVBAoMBlNBUCBTRTEOMAwGA1UECwwFVG9vbHMxDzANBgNVBAMMBnJvb3RDQTCC
ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMgq1Lz8VFNo41q0zCrZPnXM
im10M9JYUGFl5s3xRP/70scuc7EpUhQPrQy6mIUEHes7uD6kRWwViM4JtpvebH52
T+caNNk6iTcYbXC1wENRJF/A64OHeVT1RJQxN0KqVQWMYoZLFS+R1JuXVnGj0J1B
jRBwJOL4MC/mYD90k/ik6r05OH8hATk+5DzzGpPK2pawpD6nU8q/X7C1XdRNZS05
7jv6Of8aonkKl6k26+zCWgHXitOagWB2sOTBH7moQEwJSWeLR5CTr/5//FSP5TT8
aR0RO1y0X/RwIif/bobBsnPZnjvpHgb83a+5ZbZt7PRz6hrvyoQofrhh2yNSogkC
AwEAAaNTMFEwHQYDVR0OBBYEFImeXkZLHA+SYuyLyBsR5cWgSL6GMB8GA1UdIwQY
MBaAFImeXkZLHA+SYuyLyBsR5cWgSL6GMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZI
hvcNAQELBQADggEBAICitWFs3JzAH42GA/45FBYjfKqXorQp22rzQ2nAXFw9nPWC
FXNIv6EUWW4SsV5AnEnOGqpC+14/sXTiSWJnqgVk8ZzeOw8is/52cigGSno7wgcX
9me72WZxlehYsf0gdx7vZAnyrFSfJ2Q/N6EAJ1LSZe92xB4A58O7dqfNPqgtZrU2
QufA81rGqr7LiWZGzPXTX8jLTV8JuXTs/yiDawSpoInasofTJMom5zdAjYoZJrcW
m+gz4yEshWzPl6qbVGvUWYdeWQ1KI9EZXUnxPzswPjqutGlE31QGcJDXvfBTeQS+
c0XmLDf22h43UaNzYRdWc3IcPLned3qNlBPI3qY=
-----END CERTIFICATE-----

27
public/ssl/rootCA.key Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEowIBAAKCAQEAyCrUvPxUU2jjWrTMKtk+dcyKbXQz0lhQYWXmzfFE//vSxy5z
sSlSFA+tDLqYhQQd6zu4PqRFbBWIzgm2m95sfnZP5xo02TqJNxhtcLXAQ1EkX8Dr
g4d5VPVElDE3QqpVBYxihksVL5HUm5dWcaPQnUGNEHAk4vgwL+ZgP3ST+KTqvTk4
fyEBOT7kPPMak8ralrCkPqdTyr9fsLVd1E1lLTnuO/o5/xqieQqXqTbr7MJaAdeK
05qBYHaw5MEfuahATAlJZ4tHkJOv/n/8VI/lNPxpHRE7XLRf9HAiJ/9uhsGyc9me
O+keBvzdr7lltm3s9HPqGu/KhCh+uGHbI1KiCQIDAQABAoIBAAVr240uzF3h9l5r
jSgP8DgijRE/13N3/t1UdDbZtQO131STtoBy3Q08C3TPzPe1T9YiLPBNZK/zuVvT
OYXpNUkLjUh2Fj5X7oV2fOhTk9x+4xxQzlAmqCub5PqahqOgl2LqFXULrYw3R+na
5HV5eVn4/4gVcXpQPIXfmHW/g451ZL444jcn1TQYnE0CxlUastc5kaltCR53TWY0
5UNGbbhnbDm5d04uYBFo+a+5MmYSVJ5KDf/BrUBMKcjPetnv0jQfoBao+oka2uie
42dqtRWJG2JiJXXG8sSCiLHW9qPgjp8wVgb79AkMpIjdlabQvaI5q/7pSVyf1x2h
bLhVI4ECgYEA58RINaEZkSYhwhUnvY1agBGHajmAAz8krgyPRGj/HzYmLbwUgZI7
OIuB6uiWgK3VtP49oVMA5szrkMW4V5pKgL9piSzCOIKtRImblOFQcqKxCt0MrSzx
D1kwJ1YIpFueZwZ9/ngZttKhIRRscNkJUSazeFi2gDrKjKXoms4LyLECgYEA3Ri5
kMeF3yNwJmSAmupPemeuExR8L00YC5B93WWUzNcJ2pVJhSHHAPZ4OB4Z+7iLoCpM
/5iWku+kySg6AugH6fWlDoC5mTXLTa11M+rwVv1INO5PSWbxPoMe7DMTtbYkhUxW
HMMXg1P9eS4a1fFiPHnEvT+ovKuOJ4MJIzwOxNkCgYAiw1gpYx6YnOWXXOD3F4qp
hveOwU0oL4Jq8MtUcYNCxTZ4yasxvCNR2esEtxpL9scFPNU1q2OJOtdigaWiziu6
n/tObf47x64Bh7pkXF9asnhnrrxGBWWq7a/BVrA5JtzdiyW+03jX6UPt2EhjrMou
9+UXegb1uNvEuOXowlsWIQKBgEcvx8eaxjqzIU/rOhEm8hIaQcz44ockTmKi0jOv
mjpd3llXicVou7dOpCSFZJ5MrAAUvpfpHEoRCMCPyCXZaXrl0ZAa2CdBT8Uh3UOr
GFkZ0d7g//xFPdV/yDwKsgTmsVmN24gFNJPfPhR/SLqrrpKELlk0nvKoVevY399N
Xf/5AoGBAMTYf04U30iMgjwrXCQAebCKA641DshyxplYiTZYddhGUigUslxrrSA9
stdRoYmwlmXwwtGEyu/064sZiOQap8+MtL/mUrdpHzZfy+xK883d6UnYe/iTONgc
j7kBt543WxzQSRW/1l58xgZWltJlCE5EZCKXA7fX+IoIQZQnYRI4
-----END RSA PRIVATE KEY-----

1
public/ssl/rootCA.srl Normal file
View File

@ -0,0 +1 @@
0DE7FFB7FF93E6FD83FED6EB3A1D83EBB6A82DC1

20
public/ssl/server.crt Normal file
View File

@ -0,0 +1,20 @@
-----BEGIN CERTIFICATE-----
MIIDUjCCAjoCFA3n/7f/k+b9g/7W6zodg+u2qC3AMA0GCSqGSIb3DQEBCwUAMGQx
CzAJBgNVBAYTAkRFMRAwDgYDVQQIDAdHZXJtYW55MREwDwYDVQQHDAhXYWxsZG9y
ZjEPMA0GA1UECgwGU0FQIFNFMQ4wDAYDVQQLDAVUb29sczEPMA0GA1UEAwwGcm9v
dENBMB4XDTIwMDMyNzIxMTkxNFoXDTIxMDgwOTIxMTkxNFowZzELMAkGA1UEBhMC
REUxEDAOBgNVBAgMB0dlcm1hbnkxETAPBgNVBAcMCFdhbGxkb3JmMQ8wDQYDVQQK
DAZTQVAgU0UxDjAMBgNVBAsMBVRvb2xzMRIwEAYDVQQDDAlsb2NhbGhvc3QwggEi
MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx+njjit6UtTPP8IImkVc5UAYc
3XKXVpCjWSqMSL3xj1O9zWPz4Ke+0mxH4mh6Ko0yO6+eBmzozSJUO1sU/Iz8v5T8
ZqqXANkF5v/zBjVMCPb6jiA9hLmJBpzGRB07fiuf17fI0lQ9HpuNNjsmm5x1fWBO
/D/KEM9218Bu9XkSAplIGg86xuvpdPpYLrxNbx9xWWlcRB7IRUIGfNbRFHWC0ryW
5kLzVSHhK3EYfAvak6mdIJ4iXySWuY4qaUE9/Iijud1JTuq9lKZS4qWdg7NmAGWH
bau2cSYWZeFc9ACAVNcE+YNLwzXyGIXCLgAtQ0vJCPj3Yf/lF9vvc2mQ114dAgMB
AAEwDQYJKoZIhvcNAQELBQADggEBAL/jf+OeGeXiX2f0ot3kYEe5XKflQb++8eop
iXbm6nqD9syWW6mpON1tZQ9EmIpT4dnh+D2+OFqM1QpF7zNZXRzIOrAfjKayq0yd
taA6zDdDUVPWAzHZz4R70UiMSXJFIDtKhWm7wEEjr72OgYC3nlYrvffhSS3pRrBF
kXRKpuuE9Yt60ciKeFssozS/wuflQ6fcDawTpwtzYU7z5p5B4KL1TmB6ZTXLfmD3
aotONmHOKqNUKdvgNfH9+09S3/bNsbSsA5epWjR9rm/PidRyk4x1UZEc3FAoSkGq
4r8TBc1LXsMk6TxUTRzEbtxCsoAllpPivi+cyGUNf+iF/FIWD+U=
-----END CERTIFICATE-----

17
public/ssl/server.csr Normal file
View File

@ -0,0 +1,17 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICrDCCAZQCAQAwZzELMAkGA1UEBhMCREUxEDAOBgNVBAgMB0dlcm1hbnkxETAP
BgNVBAcMCFdhbGxkb3JmMQ8wDQYDVQQKDAZTQVAgU0UxDjAMBgNVBAsMBVRvb2xz
MRIwEAYDVQQDDAlsb2NhbGhvc3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQCx+njjit6UtTPP8IImkVc5UAYc3XKXVpCjWSqMSL3xj1O9zWPz4Ke+0mxH
4mh6Ko0yO6+eBmzozSJUO1sU/Iz8v5T8ZqqXANkF5v/zBjVMCPb6jiA9hLmJBpzG
RB07fiuf17fI0lQ9HpuNNjsmm5x1fWBO/D/KEM9218Bu9XkSAplIGg86xuvpdPpY
LrxNbx9xWWlcRB7IRUIGfNbRFHWC0ryW5kLzVSHhK3EYfAvak6mdIJ4iXySWuY4q
aUE9/Iijud1JTuq9lKZS4qWdg7NmAGWHbau2cSYWZeFc9ACAVNcE+YNLwzXyGIXC
LgAtQ0vJCPj3Yf/lF9vvc2mQ114dAgMBAAGgADANBgkqhkiG9w0BAQsFAAOCAQEA
I3455yEdVYmyv+9aDGNuUAPEKvnubLZOuEC6IweCT88f9cwQlvTNSkgQ8ylJ40oQ
D/akfBMQEc11NjVoRE5jFPabLMr0wC/KWL5RhXAwu82pC7l64jd8xLhHWXE1cY7h
i7pGBawcvnuqlkwPnd6OSh4c1MdHMsefBb8RKvDJ4I6iWfu1ZKBWWBknnTKwEB/y
K/jCq81z3xwlNx8r5MT43thzYMRxRIXX63Le28OurRWJNCxuyrQUh7dqGhbfXvOC
VCvFZphRc8bB9h45wvblPAgcVVDcqpKUGHvqUd456wQJ0JIer0VXhrAMIdzBiCzl
eqBFgozJ6u2jBWxvfrnHWQ==
-----END CERTIFICATE REQUEST-----

27
public/ssl/server.key Normal file
View File

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAsfp444relLUzz/CCJpFXOVAGHN1yl1aQo1kqjEi98Y9Tvc1j
8+CnvtJsR+JoeiqNMjuvngZs6M0iVDtbFPyM/L+U/GaqlwDZBeb/8wY1TAj2+o4g
PYS5iQacxkQdO34rn9e3yNJUPR6bjTY7JpucdX1gTvw/yhDPdtfAbvV5EgKZSBoP
Osbr6XT6WC68TW8fcVlpXEQeyEVCBnzW0RR1gtK8luZC81Uh4StxGHwL2pOpnSCe
Il8klrmOKmlBPfyIo7ndSU7qvZSmUuKlnYOzZgBlh22rtnEmFmXhXPQAgFTXBPmD
S8M18hiFwi4ALUNLyQj492H/5Rfb73NpkNdeHQIDAQABAoIBAD8+OebhWeaN3TNu
y1DZJJ2BCisHpciRQiRJcw0WbCiCPcecTIBEvFbafw+sLGP86t+GxgjpT5oKCsDT
trHmbFMD4PUvpj6yVmv6gcjh096I8Ppntp0lpKhEaUEqwxh45RePmAcMdlKhpbSw
KKS3dwlo2+g1SpWLE62vTPog0DzNh8WtFePAqt5SzA07fpuZSuhobchCHQpZS4Kr
Pv8mJj/uWSa3ysVqJ6FaqeIqMTNP5S5QxJw/OOLR+0Wzi8m2ET0Be16H7NO7EgXr
6xjY3GcI292oXylSFMSZkKuRf3fX08AP8hKsP7A7qjTY/S4gQ1Tte9B0s2Uq7LJx
liXmoAECgYEA3n4cfmCFZwe1NjpksKe8kLm871oq5x7UB3OsbIKPYvdp2/G3eour
175qe5oMJgJe28Jqgu7EE9zDQcGMSpV7yapbeGcIg5h7b2a1Un3TbvJIMBLBrbR6
fGwW+gL0REeLrl7vMgrUTXO1/MbiMvoa48fUea+PLW48qQ53qGh2TR0CgYEAzMgt
oY1pBTNim+0pgjQTwAi+y0Jirc6pAfunrf72onBy5Bt0arBsYMlKjZS6yaR78aqh
JNHymXRHwQZK9oMx6tLR8jT+E9LJH7Hk2Vv5M6f8xZwF/f0zc67mSEuj+mHc0X++
qd7lYmudyAfWM0+A3DUVAXUyMnoKZzvCO9fFhQECgYEAg5Vj9p3Q56EYW8znFc7t
503h3lCeRPfnf8y6caY5dNdMJQbscy49YCe+RAFUI/qM7T0qzuq0zeZnF/GGremA
P0FgPXH6CBHbFoRQwkumCtyBMuU05C1zrzgh0pSCsAr8IhEFN7xN2MyRGcDpsCpY
UtQw5hKdA8pJV9Y1kETPikUCgYA64z2r/Vw78KDksfiDxrH/QQSMstRposobFeEM
Ogt2fturGPILVBx2YKwdtq1YGwLBZg3c5rrawgN4UHTyGpwaKPHSssZ1sOHBSYjD
sJ0i66XWtZ1LgqpvE9aI56eJ8uZrIE8VzlEsUkIXKZnBO5WUvXcC6k67ETk4ooii
aNQWAQKBgQDOlUkeRQjVhm9fW8HrKdqUf4+1Zge4wwOi6q4fO4EdaSFu9KGnUOmS
crvagTexI5MPHuq7LuK4MsWrNlbxJ/axjazDDLqeaWaWOtJvO+L274yWQtRQ4/DY
tcTDKTbGln/v+x8eWW9OhUy/ADUFPkweXoemnI5iIdjymkZFGB/XlQ==
-----END RSA PRIVATE KEY-----

22
public/ssl/setup.sh Normal file
View File

@ -0,0 +1,22 @@
#!/bin/bash
# From https://github.com/thojansen/client-certificates/blob/master/ssl/setup.sh
# create rootCA certificate
openssl genrsa -out rootCA.key 2048
openssl req -x509 -new -nodes -key rootCA.key -days 1024 -out rootCA.crt -subj "/C=DE/ST=Germany/L=Walldorf/O=SAP SE/OU=Tools/CN=rootCA"
# create server key and certificate
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/C=DE/ST=Germany/L=Walldorf/O=SAP SE/OU=Tools/CN=localhost"
openssl x509 -req -in server.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out server.crt -days 500
# create client key and certificate
openssl genrsa -out client.key 2048
openssl req -new -key client.key -out client.csr -subj "/C=DE/ST=Germany/L=Walldorf/O=SAP SE/OU=Tools/CN=client"
openssl x509 -req -in client.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out client.crt -days 500
# generate client.p12 file which can be easily imported to OS.
openssl pkcs12 -export -inkey client.key -in client.crt -name client -out client.p12
# generate a non-encrypt pem file with key and crt files, from p12 files
#openssl pkcs12 -in client.p12 -out client.pem -nodes -clcerts

41
scripts/notarize.js Normal file
View File

@ -0,0 +1,41 @@
const fs = require("fs");
const path = require("path");
const { notarize } = require("electron-notarize");
const envConfig = require('dotenv').config();
Object.entries(envConfig.parsed || {}).forEach(([key, value]) => {
process.env[key] = value;
});
module.exports = async function (params) {
console.log(process.env);
// Only notarize the app on Mac OS only.
if (process.platform !== "darwin") {
return;
}
// Same appId in electron-builder.
let appId = "io.gnosis.safe.macos";
let appPath = path.join(
params.appOutDir,
`${params.packager.appInfo.productFilename}.app`
);
if (!fs.existsSync(appPath)) {
throw new Error(`Cannot find application at: ${appPath}`);
}
console.log(`Notarizing ${appId} found at ${appPath}`);
try {
await notarize({
appBundleId: appId,
appPath: appPath,
appleId: process.env.APPLEID,
appleIdPassword: process.env.APPLEIDPASS,
});
} catch (error) {
console.error(error);
}
console.log(`Done notarizing ${appId}`);
};

18
scripts/preload.js Normal file
View File

@ -0,0 +1,18 @@
// All of the Node.js APIs are available in the preload process.
// It has the same sandbox as a Chrome extension.
const TransportNodeHid = require("@ledgerhq/hw-transport-node-hid").default;
window.TransportNodeHid = TransportNodeHid;
window.isDesktop = true;
window.addEventListener('DOMContentLoaded', () => {
const replaceText = (selector, text) => {
const element = document.getElementById(selector)
if (element) element.innerText = text
}
for (const type of ['chrome', 'node', 'electron']) {
replaceText(`${type}-version`, process.versions[type])
}
})

3453
yarn.lock

File diff suppressed because it is too large Load Diff